@fundar/data-chart-telling 1.17.0 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -0
- package/README.md +2 -1
- package/dist/configuration/config.svelte.js +4 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +4 -1
- package/dist/layout/coordinates/CoordinatesLayout.svelte +3 -1
- package/dist/layout/geometry/GeometryLayout.svelte +222 -53
- package/dist/layout/geometry/ScaleFreeContext.d.ts +31 -0
- package/dist/layout/geometry/ScaleFreeContext.js +65 -0
- package/dist/layout/geometry/ScaleFreeMarks.svelte +14 -0
- package/dist/layout/geometry/ScaleFreeMarks.svelte.d.ts +7 -0
- package/dist/layout/geometry/ScaleGate.svelte.d.ts +8 -0
- package/dist/layout/geometry/ScaleGate.svelte.js +95 -0
- package/dist/layout/geometry/ScaleGateMarks.svelte +15 -0
- package/dist/layout/geometry/ScaleGateMarks.svelte.d.ts +7 -0
- package/dist/layout/hover/HoverDefaults.d.ts +52 -0
- package/dist/layout/hover/HoverDefaults.js +96 -0
- package/dist/layout/hover/HoverLayers.d.ts +35 -0
- package/dist/layout/hover/HoverLayers.js +122 -0
- package/dist/layout/hover/HoverSettings.d.ts +1 -3
- package/dist/layout/hover/HoverSettings.js +3 -2
- package/dist/layout/hover/HoverShapes.d.ts +56 -0
- package/dist/layout/hover/HoverShapes.js +163 -0
- package/dist/layout/hover/PlotHover.svelte.d.ts +18 -0
- package/dist/layout/hover/PlotHover.svelte.js +54 -1
- package/dist/layout/legend/LegendState.svelte.d.ts +2 -0
- package/dist/layout/legend/LegendState.svelte.js +5 -0
- package/dist/layout/margins/Box.d.ts +4 -0
- package/dist/layout/margins/Box.js +14 -0
- package/dist/layout/margins/PlotMargins.svelte.js +26 -1
- package/dist/layout/plot/{Plot.svelte.d.ts → AbstractPlot.svelte.d.ts} +3 -3
- package/dist/layout/plot/Core.svelte +2 -2
- package/dist/layout/plot/PublicPlotContext.d.ts +6 -0
- package/dist/layout/plot/PublicPlotContext.js +8 -0
- package/dist/layout/styles/ValueLabels.d.ts +118 -59
- package/dist/layout/styles/ValueLabels.js +313 -146
- package/dist/layout/tooltip/TooltipState.svelte.d.ts +8 -9
- package/dist/layout/tooltip/TooltipState.svelte.js +28 -29
- package/dist/markers/MarkerKinds.d.ts +84 -1
- package/dist/markers/MarkerKinds.js +150 -23
- package/dist/markers/area/AreaMarker.svelte +1 -1
- package/dist/markers/band/BandMarker.svelte +74 -0
- package/dist/markers/band/BandMarker.svelte.d.ts +7 -0
- package/dist/markers/band/Bands.d.ts +16 -0
- package/dist/markers/band/Bands.js +48 -0
- package/dist/markers/bar/BarMarker.svelte +29 -70
- package/dist/markers/bollinger/BollingerMarker.svelte +1 -1
- package/dist/markers/box/BoxMarker.svelte +1 -1
- package/dist/markers/dot/DotRadius.d.ts +11 -0
- package/dist/markers/dot/DotRadius.js +21 -0
- package/dist/markers/hover/HoverMarker.svelte +7 -265
- package/dist/markers/hover/HoverMarker.svelte.d.ts +4 -27
- package/dist/markers/labels/CurveLabel.svelte +56 -0
- package/dist/markers/labels/CurveLabel.svelte.d.ts +9 -0
- package/dist/markers/labels/LabelMerge.d.ts +11 -0
- package/dist/markers/labels/LabelMerge.js +87 -0
- package/dist/markers/labels/MarkerLabel.svelte +36 -0
- package/dist/markers/labels/MarkerLabel.svelte.d.ts +10 -0
- package/dist/markers/labels/MarkerLabels.d.ts +52 -0
- package/dist/markers/labels/MarkerLabels.js +97 -0
- package/dist/markers/labels/geometry/BoxGeometry.d.ts +8 -0
- package/dist/markers/labels/geometry/BoxGeometry.js +101 -0
- package/dist/markers/labels/geometry/CurveGeometry.d.ts +34 -0
- package/dist/markers/labels/geometry/CurveGeometry.js +193 -0
- package/dist/markers/labels/geometry/PointGeometry.d.ts +9 -0
- package/dist/markers/labels/geometry/PointGeometry.js +22 -0
- package/dist/markers/labels/layouts/BoxLayout.d.ts +10 -0
- package/dist/markers/labels/layouts/BoxLayout.js +49 -0
- package/dist/markers/labels/layouts/PathLayout.d.ts +11 -0
- package/dist/markers/labels/layouts/PathLayout.js +91 -0
- package/dist/markers/labels/layouts/PointLayout.d.ts +19 -0
- package/dist/markers/labels/layouts/PointLayout.js +94 -0
- package/dist/markers/regression/RegressionMarker.svelte +1 -1
- package/dist/markers/text/Covering.d.ts +13 -0
- package/dist/markers/text/Covering.js +29 -0
- package/dist/markers/text/Declutter.d.ts +24 -3
- package/dist/markers/text/Declutter.js +46 -3
- package/dist/markers/text/TextMarker.svelte +90 -17
- package/dist/markers/text/TextMarker.svelte.d.ts +1 -1
- package/dist/markers/tick/TickMarker.svelte +1 -1
- package/dist/markers/utils/MarkerChannels.d.ts +1 -1
- package/dist/markers/utils/MarkerChannels.js +3 -2
- package/dist/markers/utils/PointPixel.d.ts +37 -0
- package/dist/markers/utils/PointPixel.js +44 -0
- package/dist/markers/violin/ViolinMarker.svelte +1 -1
- package/dist/markers/waffle/WaffleMarker.svelte +1 -1
- package/dist/phases/Pipeline.d.ts +7 -7
- package/dist/phases/Pipeline.js +12 -9
- package/dist/phases/context/ContextPhase.d.ts +22 -0
- package/dist/phases/context/ContextPhase.js +23 -0
- package/dist/phases/context/RowContext.d.ts +37 -0
- package/dist/phases/context/RowContext.js +97 -0
- package/dist/phases/data/DataPhase.d.ts +4 -4
- package/dist/phases/data/DataPhase.js +7 -7
- package/dist/phases/hover/HoverPhase.d.ts +6 -7
- package/dist/phases/hover/HoverPhase.js +28 -23
- package/dist/phases/mapping/MappingPhase.d.ts +4 -4
- package/dist/phases/mapping/MappingPhase.js +2 -2
- package/dist/phases/markers/MarkerStyles.d.ts +8 -0
- package/dist/phases/markers/MarkerStyles.js +24 -6
- package/dist/phases/markers/MarkersPhase.d.ts +6 -7
- package/dist/phases/markers/MarkersPhase.js +18 -12
- package/dist/phases/scales/ScalesPhase.d.ts +4 -4
- package/dist/phases/scales/ScalesPhase.js +4 -4
- package/dist/phases/sharedScales/SharedScalesPhase.d.ts +2 -2
- package/dist/phases/sharedScales/SharedScalesPhase.js +2 -2
- package/dist/phases/statistics/MarkerGrouping.d.ts +0 -9
- package/dist/phases/statistics/MarkerGrouping.js +5 -48
- package/dist/phases/statistics/MarkerInheritance.d.ts +11 -0
- package/dist/phases/statistics/MarkerInheritance.js +25 -0
- package/dist/phases/statistics/MarkerOrientation.d.ts +26 -0
- package/dist/phases/statistics/MarkerOrientation.js +29 -0
- package/dist/phases/statistics/StatisticsPhase.js +15 -15
- package/dist/phases/styles/StylesPhase.d.ts +3 -3
- package/dist/phases/styles/StylesPhase.js +2 -2
- package/dist/phases/tooltip/TooltipPhase.d.ts +4 -4
- package/dist/phases/tooltip/TooltipPhase.js +10 -7
- package/dist/phases/transforms/TransformsPhase.d.ts +3 -3
- package/dist/phases/transforms/TransformsPhase.js +7 -5
- package/dist/plots/correlation/heatmap/Plot.svelte +2 -2
- package/dist/plots/correlation/heatmap/Plot.svelte.d.ts +0 -1
- package/dist/plots/correlation/heatmap/defaults.d.ts +2 -2
- package/dist/plots/correlation/heatmap/defaults.js +35 -7
- package/dist/plots/correlation/heatmap/markers.d.ts +2 -8
- package/dist/plots/correlation/heatmap/markers.js +8 -11
- package/dist/plots/correlation/scatter/Plot.svelte +2 -2
- package/dist/plots/correlation/scatter/Plot.svelte.d.ts +0 -1
- package/dist/plots/correlation/scatter/defaults.d.ts +2 -2
- package/dist/plots/correlation/scatter/defaults.js +18 -6
- package/dist/plots/correlation/scatter/markers.d.ts +2 -11
- package/dist/plots/correlation/scatter/markers.js +24 -30
- package/dist/plots/distribution/box/BoxSummaries.d.ts +22 -8
- package/dist/plots/distribution/box/BoxSummaries.js +99 -40
- package/dist/plots/distribution/box/Plot.svelte +2 -2
- package/dist/plots/distribution/box/Plot.svelte.d.ts +0 -1
- package/dist/plots/distribution/box/defaults.d.ts +2 -2
- package/dist/plots/distribution/box/defaults.js +20 -6
- package/dist/plots/distribution/box/markers.d.ts +2 -2
- package/dist/plots/distribution/box/markers.js +13 -4
- package/dist/plots/distribution/density/Plot.svelte +2 -2
- package/dist/plots/distribution/density/Plot.svelte.d.ts +0 -1
- package/dist/plots/distribution/density/defaults.d.ts +2 -2
- package/dist/plots/distribution/density/defaults.js +33 -1
- package/dist/plots/distribution/density/markers.d.ts +2 -2
- package/dist/plots/distribution/density/markers.js +9 -5
- package/dist/plots/distribution/histogram/Plot.svelte +2 -2
- package/dist/plots/distribution/histogram/Plot.svelte.d.ts +0 -1
- package/dist/plots/distribution/histogram/defaults.d.ts +2 -2
- package/dist/plots/distribution/histogram/defaults.js +36 -36
- package/dist/plots/distribution/histogram/markers.d.ts +2 -2
- package/dist/plots/distribution/histogram/markers.js +7 -6
- package/dist/plots/distribution/pyramid/Plot.svelte +2 -2
- package/dist/plots/distribution/pyramid/Plot.svelte.d.ts +0 -1
- package/dist/plots/distribution/pyramid/defaults.d.ts +2 -2
- package/dist/plots/distribution/pyramid/defaults.js +13 -3
- package/dist/plots/distribution/pyramid/markers.d.ts +2 -10
- package/dist/plots/distribution/pyramid/markers.js +9 -18
- package/dist/plots/distribution/violin/Plot.svelte +2 -2
- package/dist/plots/distribution/violin/Plot.svelte.d.ts +0 -1
- package/dist/plots/distribution/violin/defaults.d.ts +2 -2
- package/dist/plots/distribution/violin/defaults.js +20 -7
- package/dist/plots/distribution/violin/markers.d.ts +2 -2
- package/dist/plots/distribution/violin/markers.js +30 -6
- package/dist/plots/evolution/area/Plot.svelte +2 -2
- package/dist/plots/evolution/area/Plot.svelte.d.ts +0 -1
- package/dist/plots/evolution/area/defaults.d.ts +2 -2
- package/dist/plots/evolution/area/defaults.js +5 -8
- package/dist/plots/evolution/area/markers.d.ts +2 -2
- package/dist/plots/evolution/area/markers.js +7 -5
- package/dist/plots/evolution/line/Plot.svelte +2 -2
- package/dist/plots/evolution/line/Plot.svelte.d.ts +0 -1
- package/dist/plots/evolution/line/defaults.d.ts +2 -2
- package/dist/plots/evolution/line/defaults.js +5 -7
- package/dist/plots/evolution/line/markers.d.ts +2 -2
- package/dist/plots/evolution/line/markers.js +6 -4
- package/dist/plots/evolution/slope/Plot.svelte +2 -2
- package/dist/plots/evolution/slope/Plot.svelte.d.ts +0 -1
- package/dist/plots/evolution/slope/defaults.d.ts +2 -2
- package/dist/plots/evolution/slope/defaults.js +11 -6
- package/dist/plots/evolution/slope/markers.d.ts +6 -5
- package/dist/plots/evolution/slope/markers.js +19 -12
- package/dist/plots/evolution/sparkline/Plot.svelte +2 -2
- package/dist/plots/evolution/sparkline/Plot.svelte.d.ts +0 -1
- package/dist/plots/evolution/sparkline/defaults.d.ts +2 -2
- package/dist/plots/evolution/sparkline/defaults.js +5 -2
- package/dist/plots/evolution/sparkline/markers.d.ts +2 -2
- package/dist/plots/evolution/sparkline/markers.js +6 -4
- package/dist/plots/generic/Plot.svelte +42 -0
- package/dist/plots/generic/Plot.svelte.d.ts +25 -0
- package/dist/plots/generic/defaults.d.ts +4 -0
- package/dist/plots/generic/defaults.js +7 -0
- package/dist/plots/map/geo/Core.svelte +3 -3
- package/dist/plots/map/geo/Plot.svelte +2 -2
- package/dist/plots/map/geo/Plot.svelte.d.ts +0 -1
- package/dist/plots/map/geo/defaults.d.ts +2 -2
- package/dist/plots/map/geo/phases/data.d.ts +1 -1
- package/dist/plots/map/geo/phases/data.js +1 -1
- package/dist/plots/map/geo/phases/hover.d.ts +2 -2
- package/dist/plots/map/geo/phases/hover.js +3 -3
- package/dist/plots/map/geo/phases/markers.d.ts +2 -2
- package/dist/plots/map/geo/phases/markers.js +3 -3
- package/dist/plots/map/geo/phases/scales.d.ts +2 -2
- package/dist/plots/map/geo/phases/scales.js +2 -2
- package/dist/plots/part-of-a-whole/treemap/Plot.svelte +2 -2
- package/dist/plots/part-of-a-whole/treemap/Plot.svelte.d.ts +0 -1
- package/dist/plots/part-of-a-whole/treemap/defaults.d.ts +2 -2
- package/dist/plots/part-of-a-whole/treemap/defaults.js +38 -22
- package/dist/plots/ranking/bar/Plot.svelte +2 -2
- package/dist/plots/ranking/bar/Plot.svelte.d.ts +0 -1
- package/dist/plots/ranking/bar/defaults.d.ts +2 -2
- package/dist/plots/ranking/bar/defaults.js +26 -10
- package/dist/plots/ranking/bar/markers.d.ts +3 -3
- package/dist/plots/ranking/bar/markers.js +17 -33
- package/dist/plots/ranking/bullet/Plot.svelte +2 -2
- package/dist/plots/ranking/bullet/Plot.svelte.d.ts +0 -1
- package/dist/plots/ranking/bullet/defaults.d.ts +2 -2
- package/dist/plots/ranking/bullet/defaults.js +24 -4
- package/dist/plots/ranking/bullet/markers.d.ts +3 -3
- package/dist/plots/ranking/bullet/markers.js +16 -10
- package/dist/plots/ranking/cleveland/ClevelandMarkers.d.ts +4 -11
- package/dist/plots/ranking/cleveland/ClevelandMarkers.js +73 -54
- package/dist/plots/ranking/cleveland/Plot.svelte +2 -2
- package/dist/plots/ranking/cleveland/Plot.svelte.d.ts +0 -1
- package/dist/plots/ranking/cleveland/defaults.d.ts +2 -2
- package/dist/plots/ranking/cleveland/defaults.js +39 -5
- package/dist/plots/ranking/dumbbell/Plot.svelte +2 -2
- package/dist/plots/ranking/dumbbell/Plot.svelte.d.ts +0 -1
- package/dist/plots/ranking/dumbbell/defaults.d.ts +2 -2
- package/dist/plots/ranking/forest/Plot.svelte +2 -2
- package/dist/plots/ranking/forest/Plot.svelte.d.ts +0 -1
- package/dist/plots/ranking/forest/defaults.d.ts +2 -2
- package/dist/plots/ranking/lollipop/Plot.svelte +2 -2
- package/dist/plots/ranking/lollipop/Plot.svelte.d.ts +0 -1
- package/dist/plots/ranking/lollipop/defaults.d.ts +2 -2
- package/dist/types/configuration/styling.d.ts +4 -0
- package/dist/types/layout/context.d.ts +23 -0
- package/dist/types/layout/context.js +1 -0
- package/dist/types/layout/hover.d.ts +3 -0
- package/dist/types/layout/styles/bullet.d.ts +4 -1
- package/dist/types/layout/styles/values.d.ts +59 -13
- package/dist/types/layout/tooltip.d.ts +5 -10
- package/dist/types/markers/axis/area.d.ts +5 -1
- package/dist/types/markers/axis/axisBasedMarkersConfig.d.ts +2 -1
- package/dist/types/markers/axis/band.d.ts +24 -0
- package/dist/types/markers/axis/band.js +1 -0
- package/dist/types/markers/axis/bar.d.ts +7 -4
- package/dist/types/markers/axis/bollinger.d.ts +2 -1
- package/dist/types/markers/axis/box.d.ts +2 -1
- package/dist/types/markers/axis/cell.d.ts +4 -1
- package/dist/types/markers/axis/hover.d.ts +60 -15
- package/dist/types/markers/axis/line.d.ts +4 -1
- package/dist/types/markers/axis/rect.d.ts +4 -1
- package/dist/types/markers/axis/regression.d.ts +2 -1
- package/dist/types/markers/axis/tick.d.ts +2 -1
- package/dist/types/markers/axis/trail.d.ts +4 -1
- package/dist/types/markers/axis/violin.d.ts +2 -1
- package/dist/types/markers/axis/waffle.d.ts +5 -1
- package/dist/types/markers/basic/dot.d.ts +4 -1
- package/dist/types/markers/basic/text.d.ts +25 -21
- package/dist/types/markers/channels/commonMarkerConfig.d.ts +6 -2
- package/dist/types/markers/channels/commonMarkerConfigWithLabel.d.ts +5 -9
- package/dist/types/markers/channels/commonMarkerConfigWithOrientation.d.ts +5 -0
- package/dist/types/markers/channels/commonMarkerConfigWithOrientation.js +1 -0
- package/dist/types/markers/common.d.ts +1 -0
- package/dist/types/markers/common.js +1 -0
- package/dist/types/markers/labels/box.d.ts +57 -0
- package/dist/types/markers/labels/box.js +1 -0
- package/dist/types/markers/labels/common.d.ts +15 -0
- package/dist/types/markers/labels/common.js +1 -0
- package/dist/types/markers/labels/path.d.ts +52 -0
- package/dist/types/markers/labels/path.js +1 -0
- package/dist/types/markers/labels/point.d.ts +40 -0
- package/dist/types/markers/labels/point.js +1 -0
- package/dist/types/markers/traits.d.ts +10 -0
- package/dist/types/phases/context/phase.d.ts +7 -0
- package/dist/types/phases/context/phase.js +1 -0
- package/dist/types/phases/data/phase.d.ts +2 -2
- package/dist/types/phases/hover/phase.d.ts +10 -7
- package/dist/types/phases/index.d.ts +2 -1
- package/dist/types/phases/kind.d.ts +11 -8
- package/dist/types/phases/mapping/phase.d.ts +2 -2
- package/dist/types/phases/markers/phase.d.ts +3 -10
- package/dist/types/phases/scales/phase.d.ts +4 -4
- package/dist/types/phases/stage.d.ts +3 -3
- package/dist/types/phases/state.d.ts +1 -1
- package/dist/types/phases/statistics/phase.d.ts +8 -3
- package/dist/types/phases/styles/phase.d.ts +18 -5
- package/dist/types/phases/transforms/phase.d.ts +4 -2
- package/dist/types/plots/constants.d.ts +3 -17
- package/dist/types/plots/correlation/heatmap/props.d.ts +3 -2
- package/dist/types/plots/correlation/heatmap/state.d.ts +2 -2
- package/dist/types/plots/correlation/scatter/props.d.ts +3 -2
- package/dist/types/plots/correlation/scatter/state.d.ts +2 -2
- package/dist/types/plots/distribution/box/props.d.ts +28 -2
- package/dist/types/plots/distribution/box/state.d.ts +6 -17
- package/dist/types/plots/distribution/density/props.d.ts +2 -1
- package/dist/types/plots/distribution/density/state.d.ts +2 -2
- package/dist/types/plots/distribution/histogram/props.d.ts +16 -2
- package/dist/types/plots/distribution/histogram/state.d.ts +2 -2
- package/dist/types/plots/distribution/pyramid/props.d.ts +3 -2
- package/dist/types/plots/distribution/pyramid/state.d.ts +2 -2
- package/dist/types/plots/distribution/violin/props.d.ts +6 -2
- package/dist/types/plots/distribution/violin/state.d.ts +2 -2
- package/dist/types/plots/evolution/area/props.d.ts +3 -2
- package/dist/types/plots/evolution/area/state.d.ts +2 -2
- package/dist/types/plots/evolution/line/props.d.ts +3 -2
- package/dist/types/plots/evolution/line/state.d.ts +2 -2
- package/dist/types/plots/evolution/slope/state.d.ts +2 -2
- package/dist/types/plots/evolution/sparkline/state.d.ts +2 -2
- package/dist/types/plots/generic/props.d.ts +16 -0
- package/dist/types/plots/generic/props.js +1 -0
- package/dist/types/plots/generic/state.d.ts +4 -0
- package/dist/types/plots/generic/state.js +1 -0
- package/dist/types/plots/map/geo/state.d.ts +1 -1
- package/dist/types/plots/part-of-a-whole/treemap/props.d.ts +18 -6
- package/dist/types/plots/part-of-a-whole/treemap/state.d.ts +2 -2
- package/dist/types/plots/props.d.ts +3 -0
- package/dist/types/plots/ranking/bar/props.d.ts +3 -2
- package/dist/types/plots/ranking/bar/state.d.ts +2 -2
- package/dist/types/plots/ranking/bullet/state.d.ts +2 -2
- package/dist/types/plots/ranking/cleveland/props.d.ts +3 -2
- package/dist/types/plots/ranking/cleveland/state.d.ts +2 -2
- package/dist/types/plots/ranking/dumbbell/props.d.ts +3 -2
- package/dist/types/plots/ranking/dumbbell/state.d.ts +2 -2
- package/dist/types/plots/ranking/forest/props.d.ts +5 -2
- package/dist/types/plots/ranking/forest/state.d.ts +2 -2
- package/dist/types/plots/ranking/lollipop/props.d.ts +3 -2
- package/dist/types/plots/ranking/lollipop/state.d.ts +2 -2
- package/docs/architecture.md +9 -9
- package/docs/markers.md +36 -6
- package/docs/plots/evolution/line.md +1 -1
- package/docs/plots/evolution/slope.md +1 -1
- package/docs/plots/part-of-a-whole/treemap.md +36 -2
- package/docs/plots/ranking/bar.md +1 -0
- package/docs/plots/ranking/cleveland.md +1 -1
- package/docs/state.md +33 -0
- package/docs/styles-and-segments.md +2 -15
- package/docs/theming.md +2 -1
- package/docs/tooltip-and-hover.md +81 -3
- package/docs/value-labels.md +159 -0
- package/examples/BarValues.svelte +1 -1
- package/examples/LineDates.svelte +1 -1
- package/examples/ResponsiveLine.svelte +3 -1
- package/examples/TreemapHover.svelte +25 -0
- package/examples/ValueLabels.svelte +1 -1
- package/llms-full.txt +9 -7
- package/llms.txt +3 -1
- package/package.json +3 -1
- package/dist/markers/utils/BoxLabel.d.ts +0 -58
- package/dist/markers/utils/BoxLabel.js +0 -175
- package/dist/markers/utils/MarkerLabel.svelte +0 -33
- package/dist/markers/utils/MarkerLabel.svelte.d.ts +0 -10
- /package/dist/layout/plot/{Plot.svelte → AbstractPlot.svelte} +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ValueLabels } from '../../layout/styles/ValueLabels';
|
|
1
2
|
import { Transforms } from './Transforms';
|
|
2
3
|
import { ValueSelection } from './ValueSelection';
|
|
3
4
|
import { ProcessedPositions } from './ProcessedPositions';
|
|
@@ -37,7 +38,7 @@ export class TransformsPhase {
|
|
|
37
38
|
this.#options = options;
|
|
38
39
|
this.#connect = connect;
|
|
39
40
|
}
|
|
40
|
-
run = (state,
|
|
41
|
+
run = (state, env) => {
|
|
41
42
|
const options = this.#options;
|
|
42
43
|
const visible = (state.resolvedSeries ?? []);
|
|
43
44
|
// An omitted part of a whole is laid out with the rest, so they keep their places; it is dropped after.
|
|
@@ -66,7 +67,7 @@ export class TransformsPhase {
|
|
|
66
67
|
shared[valueAxis] = (row) => row[GAP_VALUE] ?? read(row);
|
|
67
68
|
}
|
|
68
69
|
const transforms = options.transforms
|
|
69
|
-
? options.transforms(state,
|
|
70
|
+
? options.transforms(state, env)
|
|
70
71
|
: (state.transforms ?? []);
|
|
71
72
|
const rescaled = TransformsPhase.#rescaled(state, transforms, shared, valueAxis);
|
|
72
73
|
if (rescaled)
|
|
@@ -129,17 +130,18 @@ export class TransformsPhase {
|
|
|
129
130
|
#labelled(state) {
|
|
130
131
|
const options = this.#options.labels;
|
|
131
132
|
const values = state.values;
|
|
132
|
-
if (!options || !(values
|
|
133
|
+
if (!options || !ValueLabels.shows(values, options.show))
|
|
133
134
|
return {};
|
|
134
135
|
const processed = state.processedData;
|
|
135
|
-
const
|
|
136
|
+
const measure = options.measure?.(state);
|
|
137
|
+
const valueAxis = measure ? 'y' : PlotAxes.valueOf(state);
|
|
136
138
|
const select = values?.select ?? options.select;
|
|
137
139
|
const selections = ValueSelection.transforms(select, values?.series, valueAxis);
|
|
138
140
|
const position = ProcessedPositions.of(processed, valueAxis);
|
|
139
141
|
const skip = options.skip?.(state);
|
|
140
142
|
const channels = {
|
|
141
143
|
x: position.x,
|
|
142
|
-
y: position.y,
|
|
144
|
+
y: measure ?? position.y,
|
|
143
145
|
group: options.group === 'category'
|
|
144
146
|
? position[PlotAxes.categoryOf(state)]
|
|
145
147
|
: SERIES_ID_KEY
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts" generics="TData extends Record<string, unknown>">
|
|
2
|
-
import
|
|
2
|
+
import AbstractPlot from '../../../layout/plot/AbstractPlot.svelte';
|
|
3
3
|
import { buildHeatmapDefaults } from './defaults';
|
|
4
4
|
import type {
|
|
5
5
|
HeatmapPlotProps,
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
});
|
|
45
45
|
</script>
|
|
46
46
|
|
|
47
|
-
<
|
|
47
|
+
<AbstractPlot
|
|
48
48
|
core={core as HeatmapPlotCoreProps<TData>}
|
|
49
49
|
defaults={buildHeatmapDefaults}
|
|
50
50
|
bind:margins
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AxisPlotDefaults } from '../../../types/phases';
|
|
2
|
-
import type { HeatmapPlotState,
|
|
2
|
+
import type { HeatmapPlotState, HeatmapPlotEnv } from '../../../types/plots/correlation/heatmap/state';
|
|
3
3
|
/**
|
|
4
4
|
* HeatmapPlot on the shared pipeline: both axes are categories. A heatmap's
|
|
5
5
|
* `color` is each cell's numeric value, which the "data" phase reads as a
|
|
@@ -8,4 +8,4 @@ import type { HeatmapPlotState, HeatmapPlotCtx } from '../../../types/plots/corr
|
|
|
8
8
|
* cell's tooltip names its coordinates and its value.
|
|
9
9
|
* Its plot defaults to: hover one cell.
|
|
10
10
|
*/
|
|
11
|
-
export declare function buildHeatmapDefaults<TData extends Record<string, unknown>>(): AxisPlotDefaults<HeatmapPlotState<TData>,
|
|
11
|
+
export declare function buildHeatmapDefaults<TData extends Record<string, unknown>>(): AxisPlotDefaults<HeatmapPlotState<TData>, HeatmapPlotEnv>;
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { ColorRamp } from '../../../utils/color';
|
|
2
|
+
import { HoverDefaults } from '../../../layout/hover/HoverDefaults';
|
|
2
3
|
import { OpacityScale } from '../../../utils/OpacityScale';
|
|
3
4
|
import { ContinuousDomain } from '../../../utils/ContinuousDomain';
|
|
4
5
|
import { buildMarks } from './markers';
|
|
6
|
+
import { RowContext } from '../../../phases/context/RowContext';
|
|
5
7
|
/**
|
|
6
8
|
* HeatmapPlot's own "scales" output, over the band axes the shared phase laid
|
|
7
9
|
* out: the color domain over every cell's value (when `color` is set), and each
|
|
8
10
|
* row's own resolved color and opacity.
|
|
9
11
|
*/
|
|
10
|
-
function extendWithColorScales(state,
|
|
12
|
+
function extendWithColorScales(state, env) {
|
|
11
13
|
const { scales, channels } = state;
|
|
12
|
-
const { range, cfg } =
|
|
14
|
+
const { range, cfg } = env;
|
|
13
15
|
const { color: colorAcc } = channels;
|
|
14
16
|
const rows = (state.processedData?.data ?? []);
|
|
15
17
|
const valueDomain = ContinuousDomain.build(scales.color?.domain, rows.map((d) => Number(colorAcc.accessor(d))), true) ?? [0, 1];
|
|
@@ -68,6 +70,14 @@ export function buildHeatmapDefaults() {
|
|
|
68
70
|
}
|
|
69
71
|
})
|
|
70
72
|
},
|
|
73
|
+
// A cell's value is its color's, not a position's.
|
|
74
|
+
context: (state) => {
|
|
75
|
+
const color = state.channels.color.accessor;
|
|
76
|
+
return ((row) => {
|
|
77
|
+
const value = Number(color(row));
|
|
78
|
+
return { value: Number.isFinite(value) ? value : undefined };
|
|
79
|
+
});
|
|
80
|
+
},
|
|
71
81
|
statistics: { inheritGrouping: false },
|
|
72
82
|
sharedScales: { fromScalesPhase: ['color'] },
|
|
73
83
|
scales: {
|
|
@@ -75,14 +85,32 @@ export function buildHeatmapDefaults() {
|
|
|
75
85
|
defaults: () => ({ x: { labelAnchor: 'right' } }),
|
|
76
86
|
extend: extendWithColorScales
|
|
77
87
|
},
|
|
78
|
-
|
|
88
|
+
transforms: {
|
|
89
|
+
// A cell's value is its color: `'min'` and `'max'` compare that.
|
|
90
|
+
labels: {
|
|
91
|
+
show: true,
|
|
92
|
+
measure: (state) => state.channels?.color.accessor
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
styles: {
|
|
96
|
+
values: {
|
|
97
|
+
show: true,
|
|
98
|
+
layout: 'box',
|
|
99
|
+
layouts: { path: { edge: 'top', side: 'inside' }, point: { anchor: 'top', side: 'above' } }
|
|
100
|
+
}
|
|
101
|
+
},
|
|
79
102
|
markers: { marks: buildMarks },
|
|
80
103
|
hover: {
|
|
81
|
-
// A
|
|
104
|
+
// A cell writes its own value: the hover only restyles the cells - the hovered one outlined.
|
|
105
|
+
marker: (_state, env) => HoverDefaults.shapes(env.cfg),
|
|
106
|
+
// A hovered cell reads as its value, as its value labels write it.
|
|
82
107
|
label: (state) => {
|
|
83
|
-
const format = state.values?.format
|
|
84
|
-
const
|
|
85
|
-
return ((row) =>
|
|
108
|
+
const format = state.values?.format;
|
|
109
|
+
const number = (v) => `${v}`;
|
|
110
|
+
return ((row) => {
|
|
111
|
+
const context = RowContext.of(row);
|
|
112
|
+
return format ? format(Number(context.value), number, context) : `${context.value}`;
|
|
113
|
+
});
|
|
86
114
|
},
|
|
87
115
|
// A cell's color is its value, not a series'.
|
|
88
116
|
decorate: () => () => ({ series: undefined, color: undefined })
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import type { HeatmapPlotState,
|
|
1
|
+
import type { HeatmapPlotState, HeatmapPlotEnv } from '../../../types/plots/correlation/heatmap/state';
|
|
2
2
|
import type { AxisBasedMarkersConfig } from '../../../types/markers/common';
|
|
3
|
-
|
|
4
|
-
* HeatmapPlot's "markers" phase: one `'cell'` marker per resolved-style
|
|
5
|
-
* bucket - svelteplot's opacity/numeric scale machinery requires
|
|
6
|
-
* `fillOpacity`/`strokeWidth` to be constant per mark instance, unlike
|
|
7
|
-
* `fill`, which stays a per-row accessor.
|
|
8
|
-
*/
|
|
9
|
-
export declare function buildMarks<TData extends Record<string, unknown>>(state: HeatmapPlotState<TData>, ctx: HeatmapPlotCtx): AxisBasedMarkersConfig[];
|
|
3
|
+
export declare function buildMarks<TData extends Record<string, unknown>>(state: HeatmapPlotState<TData>, env: HeatmapPlotEnv): AxisBasedMarkersConfig[];
|
|
@@ -8,15 +8,9 @@ function readChannel(channel) {
|
|
|
8
8
|
return resolveAccessor(channel);
|
|
9
9
|
}
|
|
10
10
|
const OPACITY_STEPS = 32;
|
|
11
|
-
|
|
12
|
-
* HeatmapPlot's "markers" phase: one `'cell'` marker per resolved-style
|
|
13
|
-
* bucket - svelteplot's opacity/numeric scale machinery requires
|
|
14
|
-
* `fillOpacity`/`strokeWidth` to be constant per mark instance, unlike
|
|
15
|
-
* `fill`, which stays a per-row accessor.
|
|
16
|
-
*/
|
|
17
|
-
export function buildMarks(state, ctx) {
|
|
11
|
+
export function buildMarks(state, env) {
|
|
18
12
|
const { segments, channels, resolveColor, resolveOpacity } = state;
|
|
19
|
-
const { range } =
|
|
13
|
+
const { range } = env;
|
|
20
14
|
const labels = state.valueLabels?.show ? state.valueLabels : undefined;
|
|
21
15
|
const getColor = channels.color.accessor;
|
|
22
16
|
// The cells are the rows the "transforms" phase left, placed by its channels.
|
|
@@ -110,9 +104,12 @@ export function buildMarks(state, ctx) {
|
|
|
110
104
|
borderRadius: group.styles.borderRadius,
|
|
111
105
|
inset: 0.5
|
|
112
106
|
},
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
hover: 'style',
|
|
108
|
+
// Each cell writes its own value, in the middle of it by default.
|
|
109
|
+
label: labels?.label(env, (d) => labels.text(d), {
|
|
110
|
+
fill: 'currentColor',
|
|
111
|
+
fontWeight: 600,
|
|
112
|
+
labelled: state.labelled
|
|
116
113
|
})
|
|
117
114
|
}));
|
|
118
115
|
return markers;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts" generics="TData extends Record<string, unknown>">
|
|
2
|
-
import
|
|
2
|
+
import AbstractPlot from '../../../layout/plot/AbstractPlot.svelte';
|
|
3
3
|
import { buildScatterDefaults } from './defaults';
|
|
4
4
|
import type {
|
|
5
5
|
ScatterPlotProps,
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
}: ScatterPlotProps<TData> = $props();
|
|
28
28
|
</script>
|
|
29
29
|
|
|
30
|
-
<
|
|
30
|
+
<AbstractPlot
|
|
31
31
|
core={core as ScatterPlotCoreProps<TData>}
|
|
32
32
|
defaults={buildScatterDefaults}
|
|
33
33
|
bind:margins
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { AxisPlotDefaults } from '../../../types/phases';
|
|
2
|
-
import type { ScatterPlotState,
|
|
2
|
+
import type { ScatterPlotState, ScatterPlotEnv } from '../../../types/plots/correlation/scatter/state';
|
|
3
3
|
/** ScatterPlot on the shared pipeline: discrete dots, its own radius-padded scales, and its own markers. Its plot defaults to: hover the exact point. */
|
|
4
|
-
export declare function buildScatterDefaults<TData extends Record<string, unknown>>(): AxisPlotDefaults<ScatterPlotState<TData>,
|
|
4
|
+
export declare function buildScatterDefaults<TData extends Record<string, unknown>>(): AxisPlotDefaults<ScatterPlotState<TData>, ScatterPlotEnv>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ProcessedPositions } from '../../../phases/transforms/ProcessedPositions';
|
|
2
|
-
import {
|
|
2
|
+
import { HoverDefaults } from '../../../layout/hover/HoverDefaults';
|
|
3
|
+
import { buildMarks } from './markers';
|
|
3
4
|
import { Margins } from '../../../layout/margins/Margins';
|
|
4
5
|
import { MarkerAxisValues } from '../../../phases/scales/MarkerAxisValues';
|
|
5
6
|
/** Stand-in max render radius for a channel-bound `r` (svelteplot's own auto sqrt scale). */
|
|
@@ -25,7 +26,7 @@ function paddedDomain(values, radiusPx, sizePx) {
|
|
|
25
26
|
* the largest dot's radius, and grown to cover what derived markers draw
|
|
26
27
|
* (a density curve's peak, a regression band).
|
|
27
28
|
*/
|
|
28
|
-
function fitDomains(state,
|
|
29
|
+
function fitDomains(state, env) {
|
|
29
30
|
const { scales, channels, groupedSeries } = state;
|
|
30
31
|
const processed = state.processedData;
|
|
31
32
|
const position = ProcessedPositions.of(processed);
|
|
@@ -39,10 +40,10 @@ function fitDomains(state, ctx) {
|
|
|
39
40
|
? r
|
|
40
41
|
: r !== undefined
|
|
41
42
|
? AUTO_SCALED_RADIUS_ESTIMATE
|
|
42
|
-
: Math.max(0, ...groupedSeries.flatMap((group) => group.visualSegments.map((seg) => seg.styles.dotRadius ??
|
|
43
|
+
: Math.max(0, ...groupedSeries.flatMap((group) => group.visualSegments.map((seg) => seg.styles.dotRadius ?? env.cfg.scatter.dotRadius)));
|
|
43
44
|
if (radius <= 0 && !extra.x.length && !extra.y.length)
|
|
44
45
|
return {};
|
|
45
|
-
const box = Margins.resolve({ ...
|
|
46
|
+
const box = Margins.resolve({ ...env.cfg.margins, ...state.margins }).contentBox(state.width, state.height);
|
|
46
47
|
const fit = {};
|
|
47
48
|
for (const [axis, size] of [
|
|
48
49
|
['x', box.width],
|
|
@@ -67,11 +68,22 @@ export function buildScatterDefaults() {
|
|
|
67
68
|
base: { flat: 'dot' }
|
|
68
69
|
}
|
|
69
70
|
},
|
|
70
|
-
transforms: { groups: 'runs' },
|
|
71
|
+
transforms: { groups: 'runs', labels: {} },
|
|
71
72
|
scales: { fit: fitDomains },
|
|
72
|
-
|
|
73
|
+
styles: {
|
|
74
|
+
values: {
|
|
75
|
+
layout: 'point',
|
|
76
|
+
layouts: { point: { side: 'above', gap: 8 }, path: { side: 'outside' } }
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
markers: { marks: buildMarks },
|
|
73
80
|
hover: {
|
|
74
81
|
strategy: 'punctual',
|
|
82
|
+
// A crosshair through the hovered point, and its label - the point is a dot already.
|
|
83
|
+
marker: () => ({
|
|
84
|
+
back: [HoverDefaults.rule('x'), HoverDefaults.rule('y')],
|
|
85
|
+
front: [HoverDefaults.text()]
|
|
86
|
+
}),
|
|
75
87
|
label: (state) => {
|
|
76
88
|
const { x, y } = state.channels;
|
|
77
89
|
return (row) => `${x.accessor(row)}, ${y.accessor(row)}`;
|
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
import type { ScatterPlotState,
|
|
2
|
-
import type { TextMarkerConfig } from '../../../types/markers/common';
|
|
3
|
-
import { ValueLabels } from '../../../layout/styles/ValueLabels';
|
|
1
|
+
import type { ScatterPlotState, ScatterPlotEnv } from '../../../types/plots/correlation/scatter/state';
|
|
4
2
|
import type { AxisBasedMarkersConfig } from '../../../types/markers/common';
|
|
5
|
-
/**
|
|
6
|
-
* ScatterPlot's `styles.values` as one `'text'` marker over the same
|
|
7
|
-
* processed rows its dots draw, each labelled with its own `y` value. A label
|
|
8
|
-
* sits beside its point and flips to the other side where its text would
|
|
9
|
-
* cross the plot's edge (`edgeAware`).
|
|
10
|
-
*/
|
|
11
|
-
export declare function buildValueLabels<TData extends Record<string, unknown>>(labels: ValueLabels, state: ScatterPlotState<TData>): TextMarkerConfig[];
|
|
12
3
|
/**
|
|
13
4
|
* ScatterPlot's "markers" phase: one `'dot'` marker per visual segment of the
|
|
14
5
|
* rows the "transforms" phase left, in their own order, so a reordering
|
|
@@ -16,4 +7,4 @@ export declare function buildValueLabels<TData extends Record<string, unknown>>(
|
|
|
16
7
|
* "statistics" phase already put in `state.markers` - and its value labels on
|
|
17
8
|
* top of everything.
|
|
18
9
|
*/
|
|
19
|
-
export declare function buildMarks<TData extends Record<string, unknown>>(state: ScatterPlotState<TData>,
|
|
10
|
+
export declare function buildMarks<TData extends Record<string, unknown>>(state: ScatterPlotState<TData>, env: ScatterPlotEnv): AxisBasedMarkersConfig[];
|
|
@@ -1,38 +1,28 @@
|
|
|
1
|
-
import { ProcessedPositions } from '../../../phases/transforms/ProcessedPositions';
|
|
2
1
|
import { SERIES_KEY } from '../../../phases/transforms/TransformsPhase';
|
|
3
2
|
import { ValueLabels } from '../../../layout/styles/ValueLabels';
|
|
4
3
|
/**
|
|
5
|
-
* ScatterPlot's `styles.values` as
|
|
6
|
-
*
|
|
7
|
-
* sits beside its point and flips to the other side where its text would
|
|
8
|
-
* cross the plot's edge (`edgeAware`).
|
|
4
|
+
* ScatterPlot's `styles.values` as labels of its dots: each labelled row with its own value, by default on a free
|
|
5
|
+
* spot around its point (`declutter: 'around'`) - a label with none is left out - or around its rim (`'path'`).
|
|
9
6
|
*/
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
if (
|
|
7
|
+
function buildValueLabels(labels, state, env) {
|
|
8
|
+
const rows = new Set(state.labelled ?? []);
|
|
9
|
+
if (rows.size === 0)
|
|
13
10
|
return [];
|
|
14
|
-
const { font, format } = labels;
|
|
15
|
-
const position = ProcessedPositions.of(processedData);
|
|
16
11
|
const nameOf = (d) => String(d[SERIES_KEY]);
|
|
17
|
-
const
|
|
12
|
+
const label = labels.label(env, (d) => labels.text(d), {
|
|
13
|
+
fill: 'currentColor',
|
|
14
|
+
seriesColor: (d) => state.colorForSeries?.(nameOf(d)),
|
|
15
|
+
fontSize: 11,
|
|
16
|
+
fontWeight: 500
|
|
17
|
+
});
|
|
18
|
+
if (labels.layout !== 'point')
|
|
19
|
+
return [label];
|
|
18
20
|
return [
|
|
19
21
|
{
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
text: (d) => format(Number(valueOf(d)), nameOf(d), d),
|
|
25
|
-
styles: {
|
|
26
|
-
...font,
|
|
27
|
-
fill: font?.fill ?? 'currentColor',
|
|
28
|
-
fontSize: font?.fontSize ?? 11,
|
|
29
|
-
fontWeight: font?.fontWeight ?? 500,
|
|
30
|
-
dx: font?.dx ?? 8,
|
|
31
|
-
dy: font?.dy ?? 0,
|
|
32
|
-
textAnchor: labels.textAnchor ?? 'start',
|
|
33
|
-
lineAnchor: font?.lineAnchor ?? 'middle'
|
|
34
|
-
},
|
|
35
|
-
edgeAware: true
|
|
22
|
+
...label,
|
|
23
|
+
select: (row) => rows.has(row),
|
|
24
|
+
// A label on its own dot stays there; one beside it moves around it to a free spot.
|
|
25
|
+
declutter: labels.side === 'on' ? undefined : 'around'
|
|
36
26
|
}
|
|
37
27
|
];
|
|
38
28
|
}
|
|
@@ -43,9 +33,9 @@ export function buildValueLabels(labels, state) {
|
|
|
43
33
|
* "statistics" phase already put in `state.markers` - and its value labels on
|
|
44
34
|
* top of everything.
|
|
45
35
|
*/
|
|
46
|
-
export function buildMarks(state,
|
|
36
|
+
export function buildMarks(state, env) {
|
|
47
37
|
const { channels, colorForSeries, scales, flat } = state;
|
|
48
|
-
const { cfg, interaction } =
|
|
38
|
+
const { cfg, interaction } = env;
|
|
49
39
|
const r = channels.r;
|
|
50
40
|
const rFn = r === undefined || typeof r === 'number' ? r : r.accessor;
|
|
51
41
|
const opacityFn = channels.opacity?.accessor;
|
|
@@ -98,6 +88,7 @@ export function buildMarks(state, ctx) {
|
|
|
98
88
|
markers.push({
|
|
99
89
|
type: 'dot',
|
|
100
90
|
data: seg.data,
|
|
91
|
+
hover: 'style',
|
|
101
92
|
// Forwarded raw (a field key or function, whatever `series.x`/`.y`
|
|
102
93
|
// is) rather than pre-resolved into a closure - `DotMarker.svelte`
|
|
103
94
|
// and svelteplot's own `resolve()` already handle a field-key
|
|
@@ -125,5 +116,8 @@ export function buildMarks(state, ctx) {
|
|
|
125
116
|
});
|
|
126
117
|
}
|
|
127
118
|
});
|
|
128
|
-
|
|
119
|
+
const labels = state.valueLabels?.show
|
|
120
|
+
? buildValueLabels(state.valueLabels, state, env)
|
|
121
|
+
: undefined;
|
|
122
|
+
return ValueLabels.onMarkers(markers, 'dot', labels);
|
|
129
123
|
}
|
|
@@ -1,19 +1,33 @@
|
|
|
1
|
-
import type { HoverPosition } from '../../../types/phases';
|
|
1
|
+
import type { HoverPosition, ProcessedRow } from '../../../types/phases';
|
|
2
2
|
import type { BoxPlotState, BoxSummaryRow } from '../../../types/plots/distribution/box/state';
|
|
3
|
+
import type { BoxSummary } from '../../../types/plots/distribution/box/props';
|
|
4
|
+
import type { PointGeometryOf } from '../../../types/markers/labels/point';
|
|
3
5
|
/**
|
|
4
|
-
* The boxes a box plot draws, one
|
|
5
|
-
*
|
|
6
|
-
*
|
|
6
|
+
* The boxes a box plot draws, one per series, category and facet panel - the same quartiles and whiskers
|
|
7
|
+
* svelteplot's `BoxX`/`BoxY` compute, worked out once as each value's context ({@link context}), so its hover and
|
|
8
|
+
* tooltip read a box rather than every value inside it ({@link of}).
|
|
7
9
|
*/
|
|
8
10
|
export declare class BoxSummaries {
|
|
9
|
-
|
|
11
|
+
#private;
|
|
12
|
+
/**
|
|
13
|
+
* Each value's context: the summary of the box it is in - its category, quartiles, whisker ends (the farthest
|
|
14
|
+
* values within 1.5 IQR of the box), how many values it has and the ones past the whiskers.
|
|
15
|
+
*/
|
|
16
|
+
static context<TData extends Record<string, unknown>>(state: BoxPlotState<TData>): (row: ProcessedRow) => BoxSummary | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* One summary row per box, in the order the processed rows first reach it, read off its first value's context.
|
|
19
|
+
* Its own context is the box's, with the median for its value, and where it sits for `x` and `y`.
|
|
20
|
+
*/
|
|
10
21
|
static of<TData extends Record<string, unknown>>(state: BoxPlotState<TData>): BoxSummaryRow[];
|
|
22
|
+
/** Where each part of a box its value labels can write sits: beside the box, at the height of its value. */
|
|
23
|
+
static partPlacements<TData extends Record<string, unknown>>(state: BoxPlotState<TData>): Record<string, Record<string, unknown>>;
|
|
24
|
+
/** Where a box's part label sits: at its category, level with the part's value, beside its band. */
|
|
25
|
+
static labelPoint<TData extends Record<string, unknown>>(state: BoxPlotState<TData>): (value: symbol) => PointGeometryOf;
|
|
11
26
|
/** Where a box's summary sits for hover: at its category, level with its median. */
|
|
12
27
|
static position<TData extends Record<string, unknown>>(state: BoxPlotState<TData>): HoverPosition;
|
|
13
28
|
/**
|
|
14
|
-
* How a hovered box reads by default: its series, when the plot groups its
|
|
15
|
-
*
|
|
16
|
-
* values fall past the whiskers.
|
|
29
|
+
* How a hovered box reads by default, from its context: its series, when the plot groups its rows; its
|
|
30
|
+
* category; then its five numbers, highest first, and how many values fall past the whiskers.
|
|
17
31
|
*/
|
|
18
32
|
static format<TData extends Record<string, unknown>>(state: BoxPlotState<TData>): (row: BoxSummaryRow) => string;
|
|
19
33
|
}
|
|
@@ -1,31 +1,41 @@
|
|
|
1
|
+
import { ValueLabels } from '../../../layout/styles/ValueLabels';
|
|
1
2
|
import { ProcessedPositions } from '../../../phases/transforms/ProcessedPositions';
|
|
2
3
|
import { quantile } from 'd3-array';
|
|
3
4
|
import { SERIES_ID_KEY, SERIES_KEY } from '../../../phases/transforms/TransformsPhase';
|
|
4
5
|
import { PANEL_KEY } from '../../../phases/facet/FacetPanels';
|
|
5
6
|
import { PlotAxes } from '../../../phases/data/PlotAxes';
|
|
6
7
|
import { TooltipState } from '../../../layout/tooltip/TooltipState.svelte';
|
|
8
|
+
import { RowContext } from '../../../phases/context/RowContext';
|
|
7
9
|
import { isGapValue } from '../../utils/gaps';
|
|
8
10
|
/** The whiskers reach this many interquartile ranges past the box, as svelteplot draws them. */
|
|
9
11
|
const WHISKER_IQR = 1.5;
|
|
10
12
|
/** A summary value as a tooltip shows it: at most two decimals. */
|
|
11
13
|
const round = (value) => String(Math.round(value * 100) / 100);
|
|
12
14
|
/**
|
|
13
|
-
* The boxes a box plot draws, one
|
|
14
|
-
*
|
|
15
|
-
*
|
|
15
|
+
* The boxes a box plot draws, one per series, category and facet panel - the same quartiles and whiskers
|
|
16
|
+
* svelteplot's `BoxX`/`BoxY` compute, worked out once as each value's context ({@link context}), so its hover and
|
|
17
|
+
* tooltip read a box rather than every value inside it ({@link of}).
|
|
16
18
|
*/
|
|
17
19
|
export class BoxSummaries {
|
|
18
|
-
/**
|
|
19
|
-
static
|
|
20
|
+
/** Which box a processed row is in: its series, panel and category. */
|
|
21
|
+
static #keyOf(state) {
|
|
22
|
+
const categoryAxis = PlotAxes.categoryOf(state);
|
|
23
|
+
const categoryOf = ProcessedPositions.of(state.processedData, PlotAxes.valueOf(state))[categoryAxis];
|
|
24
|
+
return (row) => JSON.stringify([row[SERIES_ID_KEY], row[PANEL_KEY] ?? null, String(categoryOf(row))]);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Each value's context: the summary of the box it is in - its category, quartiles, whisker ends (the farthest
|
|
28
|
+
* values within 1.5 IQR of the box), how many values it has and the ones past the whiskers.
|
|
29
|
+
*/
|
|
30
|
+
static context(state) {
|
|
20
31
|
const processed = state.processedData;
|
|
21
32
|
if (!processed?.data.length)
|
|
22
|
-
return
|
|
33
|
+
return () => undefined;
|
|
23
34
|
const valueAxis = PlotAxes.valueOf(state);
|
|
24
|
-
const categoryAxis = PlotAxes.categoryOf(state);
|
|
25
35
|
const position = ProcessedPositions.of(processed, valueAxis);
|
|
26
36
|
const valueOf = position[valueAxis];
|
|
27
|
-
const categoryOf = position[
|
|
28
|
-
const
|
|
37
|
+
const categoryOf = position[PlotAxes.categoryOf(state)];
|
|
38
|
+
const keyOf = BoxSummaries.#keyOf(state);
|
|
29
39
|
const boxes = new Map();
|
|
30
40
|
for (const row of processed.data) {
|
|
31
41
|
const value = valueOf(row);
|
|
@@ -34,41 +44,90 @@ export class BoxSummaries {
|
|
|
34
44
|
const n = Number(value);
|
|
35
45
|
if (!Number.isFinite(n))
|
|
36
46
|
continue;
|
|
37
|
-
const key =
|
|
38
|
-
row[SERIES_ID_KEY],
|
|
39
|
-
row[PANEL_KEY] ?? null,
|
|
40
|
-
String(categoryOf(row))
|
|
41
|
-
]);
|
|
47
|
+
const key = keyOf(row);
|
|
42
48
|
const box = boxes.get(key);
|
|
43
49
|
if (box)
|
|
44
50
|
box.values.push(n);
|
|
45
51
|
else
|
|
46
|
-
boxes.set(key, {
|
|
52
|
+
boxes.set(key, { category: categoryOf(row), values: [n] });
|
|
53
|
+
}
|
|
54
|
+
const summaries = new Map([...boxes].map(([key, { category, values }]) => [
|
|
55
|
+
key,
|
|
56
|
+
BoxSummaries.#summarize(category, values)
|
|
57
|
+
]));
|
|
58
|
+
return (row) => summaries.get(keyOf(row));
|
|
59
|
+
}
|
|
60
|
+
static #summarize(category, values) {
|
|
61
|
+
const sorted = values.sort((a, b) => a - b);
|
|
62
|
+
const p25 = quantile(sorted, 0.25);
|
|
63
|
+
const median = quantile(sorted, 0.5);
|
|
64
|
+
const p75 = quantile(sorted, 0.75);
|
|
65
|
+
const reach = (p75 - p25) * WHISKER_IQR;
|
|
66
|
+
const inside = sorted.filter((v) => v >= p25 - reach && v <= p75 + reach);
|
|
67
|
+
return {
|
|
68
|
+
category,
|
|
69
|
+
min: inside[0] ?? p25,
|
|
70
|
+
p25,
|
|
71
|
+
median,
|
|
72
|
+
p75,
|
|
73
|
+
max: inside.at(-1) ?? p75,
|
|
74
|
+
count: sorted.length,
|
|
75
|
+
outliers: sorted.filter((v) => v < p25 - reach || v > p75 + reach)
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* One summary row per box, in the order the processed rows first reach it, read off its first value's context.
|
|
80
|
+
* Its own context is the box's, with the median for its value, and where it sits for `x` and `y`.
|
|
81
|
+
*/
|
|
82
|
+
static of(state) {
|
|
83
|
+
const processed = state.processedData;
|
|
84
|
+
if (!processed?.data.length)
|
|
85
|
+
return [];
|
|
86
|
+
const valueAxis = PlotAxes.valueOf(state);
|
|
87
|
+
const categoryAxis = PlotAxes.categoryOf(state);
|
|
88
|
+
const categoryField = processed.channels[categoryAxis];
|
|
89
|
+
const keyOf = BoxSummaries.#keyOf(state);
|
|
90
|
+
const firsts = new Map();
|
|
91
|
+
for (const row of processed.data) {
|
|
92
|
+
const key = keyOf(row);
|
|
93
|
+
if (!firsts.has(key) && RowContext.of(row).median !== undefined)
|
|
94
|
+
firsts.set(key, row);
|
|
47
95
|
}
|
|
48
|
-
return [...
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
const median
|
|
52
|
-
const
|
|
53
|
-
const reach = (p75 - p25) * WHISKER_IQR;
|
|
54
|
-
const inside = sorted.filter((v) => v >= p25 - reach && v <= p75 + reach);
|
|
55
|
-
const category = categoryOf(first);
|
|
56
|
-
return {
|
|
96
|
+
return [...firsts.values()].map((first) => {
|
|
97
|
+
// The box's context, not its first value's row.
|
|
98
|
+
const context = { ...RowContext.of(first), row: undefined };
|
|
99
|
+
const { category, min, p25, median, p75, max, count, outliers } = context;
|
|
100
|
+
const summary = {
|
|
57
101
|
...(typeof categoryField === 'string' ? { [categoryField]: category } : {}),
|
|
58
102
|
[SERIES_KEY]: first[SERIES_KEY],
|
|
59
103
|
[SERIES_ID_KEY]: first[SERIES_ID_KEY],
|
|
60
104
|
...(first[PANEL_KEY] !== undefined ? { [PANEL_KEY]: first[PANEL_KEY] } : {}),
|
|
61
105
|
category,
|
|
62
|
-
min
|
|
106
|
+
min,
|
|
63
107
|
p25,
|
|
64
108
|
median,
|
|
65
109
|
p75,
|
|
66
|
-
max
|
|
67
|
-
count
|
|
68
|
-
outliers
|
|
110
|
+
max,
|
|
111
|
+
count,
|
|
112
|
+
outliers
|
|
69
113
|
};
|
|
114
|
+
RowContext.tag(summary, {
|
|
115
|
+
...context,
|
|
116
|
+
[valueAxis]: median,
|
|
117
|
+
[categoryAxis]: category,
|
|
118
|
+
value: median
|
|
119
|
+
});
|
|
120
|
+
return summary;
|
|
70
121
|
});
|
|
71
122
|
}
|
|
123
|
+
/** Where each part of a box its value labels can write sits: beside the box, at the height of its value. */
|
|
124
|
+
static partPlacements(state) {
|
|
125
|
+
return ValueLabels.besideBand(state, ['min', 'p25', 'median', 'p75', 'max', 'outliers']);
|
|
126
|
+
}
|
|
127
|
+
/** Where a box's part label sits: at its category, level with the part's value, beside its band. */
|
|
128
|
+
static labelPoint(state) {
|
|
129
|
+
return ValueLabels.bandPoint(state, 'category');
|
|
130
|
+
}
|
|
72
131
|
/** Where a box's summary sits for hover: at its category, level with its median. */
|
|
73
132
|
static position(state) {
|
|
74
133
|
const valueAxis = PlotAxes.valueOf(state);
|
|
@@ -79,22 +138,22 @@ export class BoxSummaries {
|
|
|
79
138
|
return at;
|
|
80
139
|
}
|
|
81
140
|
/**
|
|
82
|
-
* How a hovered box reads by default: its series, when the plot groups its
|
|
83
|
-
*
|
|
84
|
-
* values fall past the whiskers.
|
|
141
|
+
* How a hovered box reads by default, from its context: its series, when the plot groups its rows; its
|
|
142
|
+
* category; then its five numbers, highest first, and how many values fall past the whiskers.
|
|
85
143
|
*/
|
|
86
144
|
static format(state) {
|
|
87
145
|
const grouped = state.channels?.grouping !== undefined;
|
|
88
146
|
return (row) => {
|
|
89
|
-
const
|
|
90
|
-
lines
|
|
91
|
-
lines.push(
|
|
92
|
-
lines.push(`
|
|
93
|
-
lines.push(`
|
|
94
|
-
lines.push(`
|
|
95
|
-
lines.push(`
|
|
96
|
-
|
|
97
|
-
|
|
147
|
+
const box = RowContext.of(row);
|
|
148
|
+
const lines = grouped ? [String(box.series)] : [];
|
|
149
|
+
lines.push(TooltipState.value(box.category));
|
|
150
|
+
lines.push(`max: ${round(box.max)}`);
|
|
151
|
+
lines.push(`p75: ${round(box.p75)}`);
|
|
152
|
+
lines.push(`median: ${round(box.median)}`);
|
|
153
|
+
lines.push(`p25: ${round(box.p25)}`);
|
|
154
|
+
lines.push(`min: ${round(box.min)}`);
|
|
155
|
+
if (box.outliers.length)
|
|
156
|
+
lines.push(`outliers: ${box.outliers.length}`);
|
|
98
157
|
return lines.join('\n');
|
|
99
158
|
};
|
|
100
159
|
}
|