@voila.dev/chart 4.0.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/README.md +85 -0
- package/dist/brush/brush-layer.d.ts +16 -0
- package/dist/brush/brush-layer.d.ts.map +1 -0
- package/dist/brush/brush-layer.js +137 -0
- package/dist/brush/brush-layer.js.map +7 -0
- package/dist/brush/index.d.ts +10 -0
- package/dist/brush/index.d.ts.map +1 -0
- package/dist/brush/index.js +8 -0
- package/dist/brush/index.js.map +7 -0
- package/dist/canvas/canvas-renderer.d.ts +11 -0
- package/dist/canvas/canvas-renderer.d.ts.map +1 -0
- package/dist/canvas/canvas-renderer.js +49 -0
- package/dist/canvas/canvas-renderer.js.map +7 -0
- package/dist/canvas/index.d.ts +2 -0
- package/dist/canvas/index.d.ts.map +1 -0
- package/dist/canvas/index.js +5 -0
- package/dist/canvas/index.js.map +7 -0
- package/dist/canvas/paint-scene.d.ts +4 -0
- package/dist/canvas/paint-scene.d.ts.map +1 -0
- package/dist/canvas/paint-scene.js +130 -0
- package/dist/canvas/paint-scene.js.map +7 -0
- package/dist/canvas/resolve-color.d.ts +18 -0
- package/dist/canvas/resolve-color.d.ts.map +1 -0
- package/dist/canvas/resolve-color.js +52 -0
- package/dist/canvas/resolve-color.js.map +7 -0
- package/dist/contour/density.d.ts +20 -0
- package/dist/contour/density.d.ts.map +1 -0
- package/dist/contour/density.js +59 -0
- package/dist/contour/density.js.map +7 -0
- package/dist/contour/index.d.ts +2 -0
- package/dist/contour/index.d.ts.map +1 -0
- package/dist/contour/index.js +5 -0
- package/dist/contour/index.js.map +7 -0
- package/dist/core/channel.d.ts +11 -0
- package/dist/core/channel.d.ts.map +1 -0
- package/dist/core/channel.js +44 -0
- package/dist/core/channel.js.map +7 -0
- package/dist/core/compile.d.ts +22 -0
- package/dist/core/compile.d.ts.map +1 -0
- package/dist/core/compile.js +295 -0
- package/dist/core/compile.js.map +7 -0
- package/dist/core/define-chart.d.ts +96 -0
- package/dist/core/define-chart.d.ts.map +1 -0
- package/dist/core/define-chart.js +7 -0
- package/dist/core/define-chart.js.map +7 -0
- package/dist/core/facet.d.ts +7 -0
- package/dist/core/facet.d.ts.map +1 -0
- package/dist/core/facet.js +134 -0
- package/dist/core/facet.js.map +7 -0
- package/dist/core/format.d.ts +37 -0
- package/dist/core/format.d.ts.map +1 -0
- package/dist/core/format.js +108 -0
- package/dist/core/format.js.map +7 -0
- package/dist/core/guides/axes.d.ts +25 -0
- package/dist/core/guides/axes.d.ts.map +1 -0
- package/dist/core/guides/axes.js +204 -0
- package/dist/core/guides/axes.js.map +7 -0
- package/dist/core/marks/area.d.ts +23 -0
- package/dist/core/marks/area.d.ts.map +1 -0
- package/dist/core/marks/area.js +187 -0
- package/dist/core/marks/area.js.map +7 -0
- package/dist/core/marks/bar.d.ts +26 -0
- package/dist/core/marks/bar.d.ts.map +1 -0
- package/dist/core/marks/bar.js +200 -0
- package/dist/core/marks/bar.js.map +7 -0
- package/dist/core/marks/cell.d.ts +16 -0
- package/dist/core/marks/cell.d.ts.map +1 -0
- package/dist/core/marks/cell.js +98 -0
- package/dist/core/marks/cell.js.map +7 -0
- package/dist/core/marks/dot.d.ts +17 -0
- package/dist/core/marks/dot.d.ts.map +1 -0
- package/dist/core/marks/dot.js +125 -0
- package/dist/core/marks/dot.js.map +7 -0
- package/dist/core/marks/funnel-layout.d.ts +37 -0
- package/dist/core/marks/funnel-layout.d.ts.map +1 -0
- package/dist/core/marks/funnel-layout.js +61 -0
- package/dist/core/marks/funnel-layout.js.map +7 -0
- package/dist/core/marks/funnel.d.ts +19 -0
- package/dist/core/marks/funnel.d.ts.map +1 -0
- package/dist/core/marks/funnel.js +143 -0
- package/dist/core/marks/funnel.js.map +7 -0
- package/dist/core/marks/line.d.ts +17 -0
- package/dist/core/marks/line.d.ts.map +1 -0
- package/dist/core/marks/line.js +150 -0
- package/dist/core/marks/line.js.map +7 -0
- package/dist/core/marks/polar.d.ts +61 -0
- package/dist/core/marks/polar.d.ts.map +1 -0
- package/dist/core/marks/polar.js +436 -0
- package/dist/core/marks/polar.js.map +7 -0
- package/dist/core/marks/rect.d.ts +22 -0
- package/dist/core/marks/rect.d.ts.map +1 -0
- package/dist/core/marks/rect.js +119 -0
- package/dist/core/marks/rect.js.map +7 -0
- package/dist/core/marks/rule.d.ts +17 -0
- package/dist/core/marks/rule.d.ts.map +1 -0
- package/dist/core/marks/rule.js +73 -0
- package/dist/core/marks/rule.js.map +7 -0
- package/dist/core/marks/shared.d.ts +41 -0
- package/dist/core/marks/shared.d.ts.map +1 -0
- package/dist/core/marks/shared.js +74 -0
- package/dist/core/marks/shared.js.map +7 -0
- package/dist/core/marks/stack.d.ts +13 -0
- package/dist/core/marks/stack.d.ts.map +1 -0
- package/dist/core/marks/stack.js +28 -0
- package/dist/core/marks/stack.js.map +7 -0
- package/dist/core/marks/stats/difference.d.ts +20 -0
- package/dist/core/marks/stats/difference.d.ts.map +1 -0
- package/dist/core/marks/stats/difference.js +168 -0
- package/dist/core/marks/stats/difference.js.map +7 -0
- package/dist/core/marks/stats/distribution.d.ts +41 -0
- package/dist/core/marks/stats/distribution.d.ts.map +1 -0
- package/dist/core/marks/stats/distribution.js +354 -0
- package/dist/core/marks/stats/distribution.js.map +7 -0
- package/dist/core/marks/stats/dodge.d.ts +16 -0
- package/dist/core/marks/stats/dodge.d.ts.map +1 -0
- package/dist/core/marks/stats/dodge.js +104 -0
- package/dist/core/marks/stats/dodge.js.map +7 -0
- package/dist/core/marks/stats/hexbin.d.ts +26 -0
- package/dist/core/marks/stats/hexbin.d.ts.map +1 -0
- package/dist/core/marks/stats/hexbin.js +113 -0
- package/dist/core/marks/stats/hexbin.js.map +7 -0
- package/dist/core/marks/stats/histogram.d.ts +27 -0
- package/dist/core/marks/stats/histogram.d.ts.map +1 -0
- package/dist/core/marks/stats/histogram.js +70 -0
- package/dist/core/marks/stats/histogram.js.map +7 -0
- package/dist/core/marks/stats/regression.d.ts +13 -0
- package/dist/core/marks/stats/regression.d.ts.map +1 -0
- package/dist/core/marks/stats/regression.js +80 -0
- package/dist/core/marks/stats/regression.js.map +7 -0
- package/dist/core/marks/stats/statistics.d.ts +34 -0
- package/dist/core/marks/stats/statistics.d.ts.map +1 -0
- package/dist/core/marks/stats/statistics.js +111 -0
- package/dist/core/marks/stats/statistics.js.map +7 -0
- package/dist/core/marks/stats/waffle.d.ts +18 -0
- package/dist/core/marks/stats/waffle.d.ts.map +1 -0
- package/dist/core/marks/stats/waffle.js +117 -0
- package/dist/core/marks/stats/waffle.js.map +7 -0
- package/dist/core/marks/text.d.ts +19 -0
- package/dist/core/marks/text.d.ts.map +1 -0
- package/dist/core/marks/text.js +60 -0
- package/dist/core/marks/text.js.map +7 -0
- package/dist/core/motion/tween.d.ts +6 -0
- package/dist/core/motion/tween.d.ts.map +1 -0
- package/dist/core/motion/tween.js +98 -0
- package/dist/core/motion/tween.js.map +7 -0
- package/dist/core/nearest.d.ts +25 -0
- package/dist/core/nearest.d.ts.map +1 -0
- package/dist/core/nearest.js +151 -0
- package/dist/core/nearest.js.map +7 -0
- package/dist/core/paths.d.ts +65 -0
- package/dist/core/paths.d.ts.map +1 -0
- package/dist/core/paths.js +192 -0
- package/dist/core/paths.js.map +7 -0
- package/dist/core/scales/color.d.ts +11 -0
- package/dist/core/scales/color.d.ts.map +1 -0
- package/dist/core/scales/color.js +35 -0
- package/dist/core/scales/color.js.map +7 -0
- package/dist/core/scales/continuous.d.ts +18 -0
- package/dist/core/scales/continuous.d.ts.map +1 -0
- package/dist/core/scales/continuous.js +82 -0
- package/dist/core/scales/continuous.js.map +7 -0
- package/dist/core/scales/discrete.d.ts +22 -0
- package/dist/core/scales/discrete.d.ts.map +1 -0
- package/dist/core/scales/discrete.js +103 -0
- package/dist/core/scales/discrete.js.map +7 -0
- package/dist/core/scales/resolve.d.ts +18 -0
- package/dist/core/scales/resolve.d.ts.map +1 -0
- package/dist/core/scales/resolve.js +112 -0
- package/dist/core/scales/resolve.js.map +7 -0
- package/dist/core/scales/time.d.ts +4 -0
- package/dist/core/scales/time.d.ts.map +1 -0
- package/dist/core/scales/time.js +140 -0
- package/dist/core/scales/time.js.map +7 -0
- package/dist/core/text.d.ts +3 -0
- package/dist/core/text.d.ts.map +1 -0
- package/dist/core/text.js +29 -0
- package/dist/core/text.js.map +7 -0
- package/dist/core/theme.d.ts +8 -0
- package/dist/core/theme.d.ts.map +1 -0
- package/dist/core/theme.js +21 -0
- package/dist/core/theme.js.map +7 -0
- package/dist/core/ticks.d.ts +27 -0
- package/dist/core/ticks.d.ts.map +1 -0
- package/dist/core/ticks.js +76 -0
- package/dist/core/ticks.js.map +7 -0
- package/dist/core/types.d.ts +305 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +1 -0
- package/dist/core/types.js.map +7 -0
- package/dist/force/force.d.ts +30 -0
- package/dist/force/force.d.ts.map +1 -0
- package/dist/force/force.js +143 -0
- package/dist/force/force.js.map +7 -0
- package/dist/force/index.d.ts +2 -0
- package/dist/force/index.d.ts.map +1 -0
- package/dist/force/index.js +7 -0
- package/dist/force/index.js.map +7 -0
- package/dist/geo/geo.d.ts +59 -0
- package/dist/geo/geo.d.ts.map +1 -0
- package/dist/geo/geo.js +231 -0
- package/dist/geo/geo.js.map +7 -0
- package/dist/geo/index.d.ts +2 -0
- package/dist/geo/index.d.ts.map +1 -0
- package/dist/geo/index.js +13 -0
- package/dist/geo/index.js.map +7 -0
- package/dist/hierarchy/hierarchy.d.ts +24 -0
- package/dist/hierarchy/hierarchy.d.ts.map +1 -0
- package/dist/hierarchy/hierarchy.js +279 -0
- package/dist/hierarchy/hierarchy.js.map +7 -0
- package/dist/hierarchy/index.d.ts +2 -0
- package/dist/hierarchy/index.d.ts.map +1 -0
- package/dist/hierarchy/index.js +11 -0
- package/dist/hierarchy/index.js.map +7 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +96 -0
- package/dist/index.js.map +7 -0
- package/dist/react/brush-contract.d.ts +23 -0
- package/dist/react/brush-contract.d.ts.map +1 -0
- package/dist/react/brush-contract.js +7 -0
- package/dist/react/brush-contract.js.map +7 -0
- package/dist/react/chart-data-table.d.ts +18 -0
- package/dist/react/chart-data-table.d.ts.map +1 -0
- package/dist/react/chart-data-table.js +55 -0
- package/dist/react/chart-data-table.js.map +7 -0
- package/dist/react/chart-legend.d.ts +17 -0
- package/dist/react/chart-legend.d.ts.map +1 -0
- package/dist/react/chart-legend.js +126 -0
- package/dist/react/chart-legend.js.map +7 -0
- package/dist/react/chart-tooltip.d.ts +18 -0
- package/dist/react/chart-tooltip.d.ts.map +1 -0
- package/dist/react/chart-tooltip.js +95 -0
- package/dist/react/chart-tooltip.js.map +7 -0
- package/dist/react/chart.d.ts +45 -0
- package/dist/react/chart.d.ts.map +1 -0
- package/dist/react/chart.js +383 -0
- package/dist/react/chart.js.map +7 -0
- package/dist/react/focus-overlay.d.ts +14 -0
- package/dist/react/focus-overlay.d.ts.map +1 -0
- package/dist/react/focus-overlay.js +147 -0
- package/dist/react/focus-overlay.js.map +7 -0
- package/dist/react/index.d.ts +7 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +11 -0
- package/dist/react/index.js.map +7 -0
- package/dist/react/messages.d.ts +16 -0
- package/dist/react/messages.d.ts.map +1 -0
- package/dist/react/messages.js +33 -0
- package/dist/react/messages.js.map +7 -0
- package/dist/react/renderer.d.ts +14 -0
- package/dist/react/renderer.d.ts.map +1 -0
- package/dist/react/renderer.js +1 -0
- package/dist/react/renderer.js.map +7 -0
- package/dist/react/sr-only.d.ts +4 -0
- package/dist/react/sr-only.d.ts.map +1 -0
- package/dist/react/sr-only.js +15 -0
- package/dist/react/sr-only.js.map +7 -0
- package/dist/react/svg-renderer.d.ts +4 -0
- package/dist/react/svg-renderer.d.ts.map +1 -0
- package/dist/react/svg-renderer.js +20 -0
- package/dist/react/svg-renderer.js.map +7 -0
- package/dist/react/svg-scene.d.ts +8 -0
- package/dist/react/svg-scene.d.ts.map +1 -0
- package/dist/react/svg-scene.js +121 -0
- package/dist/react/svg-scene.js.map +7 -0
- package/dist/react/use-animated-scene.d.ts +10 -0
- package/dist/react/use-animated-scene.d.ts.map +1 -0
- package/dist/react/use-animated-scene.js +41 -0
- package/dist/react/use-animated-scene.js.map +7 -0
- package/dist/react/use-chart-focus.d.ts +29 -0
- package/dist/react/use-chart-focus.d.ts.map +1 -0
- package/dist/react/use-chart-focus.js +180 -0
- package/dist/react/use-chart-focus.js.map +7 -0
- package/dist/react/use-chart-width.d.ts +12 -0
- package/dist/react/use-chart-width.d.ts.map +1 -0
- package/dist/react/use-chart-width.js +23 -0
- package/dist/react/use-chart-width.js.map +7 -0
- package/dist/react/use-chart-zoom.d.ts +13 -0
- package/dist/react/use-chart-zoom.d.ts.map +1 -0
- package/dist/react/use-chart-zoom.js +52 -0
- package/dist/react/use-chart-zoom.js.map +7 -0
- package/dist/react/use-text-measurer.d.ts +8 -0
- package/dist/react/use-text-measurer.d.ts.map +1 -0
- package/dist/react/use-text-measurer.js +44 -0
- package/dist/react/use-text-measurer.js.map +7 -0
- package/dist/sankey/index.d.ts +2 -0
- package/dist/sankey/index.d.ts.map +1 -0
- package/dist/sankey/index.js +7 -0
- package/dist/sankey/index.js.map +7 -0
- package/dist/sankey/sankey.d.ts +29 -0
- package/dist/sankey/sankey.d.ts.map +1 -0
- package/dist/sankey/sankey.js +127 -0
- package/dist/sankey/sankey.js.map +7 -0
- package/dist/voronoi/index.d.ts +2 -0
- package/dist/voronoi/index.d.ts.map +1 -0
- package/dist/voronoi/index.js +5 -0
- package/dist/voronoi/index.js.map +7 -0
- package/dist/voronoi/voronoi.d.ts +16 -0
- package/dist/voronoi/voronoi.d.ts.map +1 -0
- package/dist/voronoi/voronoi.js +62 -0
- package/dist/voronoi/voronoi.js.map +7 -0
- package/package.json +74 -0
- package/src/brush/brush-layer.tsx +174 -0
- package/src/brush/index.ts +14 -0
- package/src/canvas/canvas-renderer.tsx +56 -0
- package/src/canvas/index.ts +1 -0
- package/src/canvas/paint-scene.ts +152 -0
- package/src/canvas/resolve-color.ts +65 -0
- package/src/contour/density.ts +90 -0
- package/src/contour/index.ts +1 -0
- package/src/core/channel.ts +53 -0
- package/src/core/compile.ts +436 -0
- package/src/core/define-chart.ts +128 -0
- package/src/core/facet.ts +189 -0
- package/src/core/format.ts +163 -0
- package/src/core/guides/axes.ts +283 -0
- package/src/core/marks/area.ts +238 -0
- package/src/core/marks/bar.ts +278 -0
- package/src/core/marks/cell.ts +123 -0
- package/src/core/marks/dot.ts +157 -0
- package/src/core/marks/funnel-layout.ts +113 -0
- package/src/core/marks/funnel.ts +172 -0
- package/src/core/marks/line.ts +206 -0
- package/src/core/marks/polar.ts +568 -0
- package/src/core/marks/rect.ts +156 -0
- package/src/core/marks/rule.ts +104 -0
- package/src/core/marks/shared.ts +134 -0
- package/src/core/marks/stack.ts +42 -0
- package/src/core/marks/stats/difference.ts +205 -0
- package/src/core/marks/stats/distribution.ts +425 -0
- package/src/core/marks/stats/dodge.ts +136 -0
- package/src/core/marks/stats/hexbin.ts +152 -0
- package/src/core/marks/stats/histogram.ts +108 -0
- package/src/core/marks/stats/regression.ts +108 -0
- package/src/core/marks/stats/statistics.ts +153 -0
- package/src/core/marks/stats/waffle.ts +141 -0
- package/src/core/marks/text.ts +97 -0
- package/src/core/motion/tween.ts +131 -0
- package/src/core/nearest.ts +223 -0
- package/src/core/paths.ts +323 -0
- package/src/core/scales/color.ts +51 -0
- package/src/core/scales/continuous.ts +111 -0
- package/src/core/scales/discrete.ts +156 -0
- package/src/core/scales/resolve.ts +158 -0
- package/src/core/scales/time.ts +180 -0
- package/src/core/text.ts +42 -0
- package/src/core/theme.ts +26 -0
- package/src/core/ticks.ts +118 -0
- package/src/core/types.ts +358 -0
- package/src/force/force.ts +200 -0
- package/src/force/index.ts +6 -0
- package/src/geo/geo.ts +346 -0
- package/src/geo/index.ts +10 -0
- package/src/hierarchy/hierarchy.ts +377 -0
- package/src/hierarchy/index.ts +6 -0
- package/src/index.ts +70 -0
- package/src/react/brush-contract.ts +35 -0
- package/src/react/chart-data-table.tsx +98 -0
- package/src/react/chart-legend.tsx +130 -0
- package/src/react/chart-tooltip.tsx +111 -0
- package/src/react/chart.tsx +489 -0
- package/src/react/focus-overlay.tsx +164 -0
- package/src/react/index.ts +9 -0
- package/src/react/messages.ts +49 -0
- package/src/react/renderer.ts +15 -0
- package/src/react/sr-only.ts +14 -0
- package/src/react/svg-renderer.tsx +18 -0
- package/src/react/svg-scene.tsx +146 -0
- package/src/react/use-animated-scene.ts +57 -0
- package/src/react/use-chart-focus.ts +245 -0
- package/src/react/use-chart-width.ts +27 -0
- package/src/react/use-chart-zoom.ts +67 -0
- package/src/react/use-text-measurer.ts +49 -0
- package/src/sankey/index.ts +6 -0
- package/src/sankey/sankey.ts +179 -0
- package/src/voronoi/index.ts +1 -0
- package/src/voronoi/voronoi.ts +84 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/core/marks/funnel-layout.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Funnel geometry, worked out away from React so it can be asserted on\n * directly. One slice per step: a horizontal band whose left edge is as tall\n * as the step's value and whose right edge slopes down to the next step's\n * value, so the drop between two steps is visible as the flank itself.\n */\n\nexport interface FunnelSlice {\n\t/** Index of the datum, i.e. of the category slot. */\n\treadonly index: number;\n\treadonly value: number;\n\t/** Left edge of the band, in plot coordinates. */\n\treadonly x: number;\n\treadonly width: number;\n\t/** Height of the left flank, proportional to the step's value. */\n\treadonly leftHeight: number;\n\t/** Height of the right flank \u2014 the next step's value, or its own on the last step. */\n\treadonly rightHeight: number;\n\t/** The trapezoid, vertically centred on the band. `\"\"` when there is nothing to draw. */\n\treadonly path: string;\n\t/** Conversion into the next step. `null` on the last step or when this one is empty. */\n\treadonly ratioToNext: number | null;\n}\n\nexport interface FunnelLayoutOptions {\n\treadonly values: ReadonlyArray<number>;\n\treadonly innerWidth: number;\n\treadonly innerHeight: number;\n\t/** Pixels of blank between two bands. */\n\treadonly gap?: number;\n\t/** Vertical centre line of the funnel. Defaults to half the inner height. */\n\treadonly centerY?: number;\n\t/** Height the largest value maps to. Defaults to the inner height. */\n\treadonly maxHeight?: number;\n\t/** Left edge of the first band. */\n\treadonly originX?: number;\n}\n\nconst DEFAULT_GAP = 4;\nconst PATH_PRECISION = 2;\n\nfunction round(value: number): number {\n\tconst factor = 10 ** PATH_PRECISION;\n\treturn Math.round(value * factor) / factor;\n}\n\nfunction point(x: number, y: number): string {\n\treturn `${round(x)},${round(y)}`;\n}\n\nfunction trapezoidPath(\n\tx: number,\n\twidth: number,\n\tcenterY: number,\n\tleftHeight: number,\n\trightHeight: number,\n): string {\n\tif (width <= 0 || (leftHeight <= 0 && rightHeight <= 0)) {\n\t\treturn \"\";\n\t}\n\tconst right = x + width;\n\treturn [\n\t\t`M${point(x, centerY - leftHeight / 2)}`,\n\t\t`L${point(right, centerY - rightHeight / 2)}`,\n\t\t`L${point(right, centerY + rightHeight / 2)}`,\n\t\t`L${point(x, centerY + leftHeight / 2)}`,\n\t\t\"Z\",\n\t].join(\"\");\n}\n\nexport function funnelSlices(\n\toptions: FunnelLayoutOptions,\n): ReadonlyArray<FunnelSlice> {\n\tconst {\n\t\tvalues,\n\t\tinnerWidth,\n\t\tinnerHeight,\n\t\tgap = DEFAULT_GAP,\n\t\tcenterY = innerHeight / 2,\n\t\tmaxHeight = innerHeight,\n\t\toriginX = 0,\n\t} = options;\n\n\tconst count = values.length;\n\tif (count === 0 || innerWidth <= 0 || maxHeight <= 0) {\n\t\treturn [];\n\t}\n\n\tconst clamped = values.map((value) => Math.max(0, value));\n\tconst peak = Math.max(...clamped);\n\tconst heightFor = (value: number): number =>\n\t\tpeak <= 0 ? 0 : (value / peak) * maxHeight;\n\n\tconst bandWidth = Math.max(0, (innerWidth - gap * (count - 1)) / count);\n\n\treturn clamped.map((value, index) => {\n\t\tconst next = clamped[index + 1];\n\t\tconst leftHeight = heightFor(value);\n\t\t// The last band has no next step to taper into, so it stays a rectangle.\n\t\tconst rightHeight = next === undefined ? leftHeight : heightFor(next);\n\t\tconst x = originX + index * (bandWidth + gap);\n\t\treturn {\n\t\t\tindex,\n\t\t\tvalue: values[index],\n\t\t\tx,\n\t\t\twidth: bandWidth,\n\t\t\tleftHeight,\n\t\t\trightHeight,\n\t\t\tpath: trapezoidPath(x, bandWidth, centerY, leftHeight, rightHeight),\n\t\t\tratioToNext: next === undefined || value <= 0 ? null : next / value,\n\t\t};\n\t});\n}\n"],
|
|
5
|
+
"mappings": "AAsCA,MAAM,cAAc;AACpB,MAAM,iBAAiB;AAEvB,SAAS,MAAM,OAAuB;AACrC,QAAM,SAAS,MAAM;AACrB,SAAO,KAAK,MAAM,QAAQ,MAAM,IAAI;AACrC;AAEA,SAAS,MAAM,GAAW,GAAmB;AAC5C,SAAO,GAAG,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC;AAC/B;AAEA,SAAS,cACR,GACA,OACA,SACA,YACA,aACS;AACT,MAAI,SAAS,KAAM,cAAc,KAAK,eAAe,GAAI;AACxD,WAAO;AAAA,EACR;AACA,QAAM,QAAQ,IAAI;AAClB,SAAO;AAAA,IACN,IAAI,MAAM,GAAG,UAAU,aAAa,CAAC,CAAC;AAAA,IACtC,IAAI,MAAM,OAAO,UAAU,cAAc,CAAC,CAAC;AAAA,IAC3C,IAAI,MAAM,OAAO,UAAU,cAAc,CAAC,CAAC;AAAA,IAC3C,IAAI,MAAM,GAAG,UAAU,aAAa,CAAC,CAAC;AAAA,IACtC;AAAA,EACD,EAAE,KAAK,EAAE;AACV;AAEO,SAAS,aACf,SAC6B;AAC7B,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,UAAU,cAAc;AAAA,IACxB,YAAY;AAAA,IACZ,UAAU;AAAA,EACX,IAAI;AAEJ,QAAM,QAAQ,OAAO;AACrB,MAAI,UAAU,KAAK,cAAc,KAAK,aAAa,GAAG;AACrD,WAAO,CAAC;AAAA,EACT;AAEA,QAAM,UAAU,OAAO,IAAI,CAAC,UAAU,KAAK,IAAI,GAAG,KAAK,CAAC;AACxD,QAAM,OAAO,KAAK,IAAI,GAAG,OAAO;AAChC,QAAM,YAAY,CAAC,UAClB,QAAQ,IAAI,IAAK,QAAQ,OAAQ;AAElC,QAAM,YAAY,KAAK,IAAI,IAAI,aAAa,OAAO,QAAQ,MAAM,KAAK;AAEtE,SAAO,QAAQ,IAAI,CAAC,OAAO,UAAU;AACpC,UAAM,OAAO,QAAQ,QAAQ,CAAC;AAC9B,UAAM,aAAa,UAAU,KAAK;AAElC,UAAM,cAAc,SAAS,SAAY,aAAa,UAAU,IAAI;AACpE,UAAM,IAAI,UAAU,SAAS,YAAY;AACzC,WAAO;AAAA,MACN;AAAA,MACA,OAAO,OAAO,KAAK;AAAA,MACnB;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,MAAM,cAAc,GAAG,WAAW,SAAS,YAAY,WAAW;AAAA,MAClE,aAAa,SAAS,UAAa,SAAS,IAAI,OAAO,OAAO;AAAA,IAC/D;AAAA,EACD,CAAC;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ChartMarkOptions } from "./shared.js";
|
|
2
|
+
import type { ChartAccessor, ChartMark, ChartValue } from "../types.js";
|
|
3
|
+
export interface FunnelOptions<TDatum> extends ChartMarkOptions<TDatum> {
|
|
4
|
+
/** The step: "Visites", "Inscriptions", "Missions". */
|
|
5
|
+
readonly category: ChartAccessor<TDatum, ChartValue>;
|
|
6
|
+
readonly value: ChartAccessor<TDatum, ChartValue>;
|
|
7
|
+
/** Pixels of blank between two steps. */
|
|
8
|
+
readonly gap?: number;
|
|
9
|
+
readonly fill?: string;
|
|
10
|
+
/** `false` drops the step name and value written above each step. */
|
|
11
|
+
readonly labels?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Steps left to right, each as tall as its value, each sloping down to the
|
|
15
|
+
* next: the drop between two stages is the shape itself. The tooltip gives
|
|
16
|
+
* the conversion from the step before.
|
|
17
|
+
*/
|
|
18
|
+
export declare function funnel<TDatum>(data: ReadonlyArray<TDatum>, options: FunnelOptions<TDatum>): ChartMark;
|
|
19
|
+
//# sourceMappingURL=funnel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"funnel.d.ts","sourceRoot":"","sources":["../../../src/core/marks/funnel.ts"],"names":[],"mappings":"AAQA,OAAO,EACN,KAAK,gBAAgB,EAIrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EACX,aAAa,EACb,SAAS,EAET,UAAU,EAEV,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,aAAa,CAAC,MAAM,CAAE,SAAQ,gBAAgB,CAAC,MAAM,CAAC;IACtE,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACrD,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClD,yCAAyC;IACzC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC1B;AAKD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAC5B,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAC3B,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAC5B,SAAS,CA8HX"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import {
|
|
2
|
+
channelLabel,
|
|
3
|
+
isPlaceable,
|
|
4
|
+
numericValue,
|
|
5
|
+
readChannel
|
|
6
|
+
} from "../channel.js";
|
|
7
|
+
import { formatPercentage } from "../format.js";
|
|
8
|
+
import { funnelSlices } from "./funnel-layout.js";
|
|
9
|
+
import {
|
|
10
|
+
markId,
|
|
11
|
+
paint,
|
|
12
|
+
seriesResolver
|
|
13
|
+
} from "./shared.js";
|
|
14
|
+
import { categoryKey } from "../scales/discrete.js";
|
|
15
|
+
const LABEL_ZONE = 36;
|
|
16
|
+
function funnel(data, options) {
|
|
17
|
+
const categories = readChannel(data, options.category);
|
|
18
|
+
const values = readChannel(data, options.value).map(
|
|
19
|
+
(value) => numericValue(value) ?? 0
|
|
20
|
+
);
|
|
21
|
+
const colorAccessor = options.color ?? options.category;
|
|
22
|
+
const colors = readChannel(data, colorAccessor);
|
|
23
|
+
return {
|
|
24
|
+
id: options.id,
|
|
25
|
+
coordinate: "frame",
|
|
26
|
+
focusOrder: "point",
|
|
27
|
+
colorLegend: options.labels === false,
|
|
28
|
+
titles: {
|
|
29
|
+
category: channelLabel(options.category),
|
|
30
|
+
value: channelLabel(options.value) ?? options.label
|
|
31
|
+
},
|
|
32
|
+
channels: {
|
|
33
|
+
color: {
|
|
34
|
+
values: colors.filter(isPlaceable),
|
|
35
|
+
label: channelLabel(colorAccessor)
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
render(context) {
|
|
39
|
+
const id = markId(options.id, "funnel", context);
|
|
40
|
+
const { plot, theme } = context;
|
|
41
|
+
const labelled = options.labels !== false;
|
|
42
|
+
const top = plot.y + (labelled ? LABEL_ZONE : 0);
|
|
43
|
+
const height = Math.max(0, plot.height - (labelled ? LABEL_ZONE : 0));
|
|
44
|
+
const slices = funnelSlices({
|
|
45
|
+
values,
|
|
46
|
+
innerWidth: plot.width,
|
|
47
|
+
innerHeight: height,
|
|
48
|
+
centerY: top + height / 2,
|
|
49
|
+
originX: plot.x,
|
|
50
|
+
gap: options.gap
|
|
51
|
+
});
|
|
52
|
+
const seriesOf = seriesResolver(
|
|
53
|
+
colors,
|
|
54
|
+
{ ...options, color: colorAccessor, fixedColor: options.fill },
|
|
55
|
+
id,
|
|
56
|
+
context
|
|
57
|
+
);
|
|
58
|
+
const nodes = [];
|
|
59
|
+
const points = [];
|
|
60
|
+
for (const slice of slices) {
|
|
61
|
+
const category = categories[slice.index];
|
|
62
|
+
if (!isPlaceable(category) || slice.path === "") {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const series = seriesOf(slice.index);
|
|
66
|
+
const key = categoryKey(category);
|
|
67
|
+
nodes.push({
|
|
68
|
+
kind: "path",
|
|
69
|
+
key: `${id}:${key}`,
|
|
70
|
+
series: series.key,
|
|
71
|
+
role: "mark",
|
|
72
|
+
d: slice.path,
|
|
73
|
+
paint: paint({ fill: series.color, opacity: options.opacity })
|
|
74
|
+
});
|
|
75
|
+
if (labelled) {
|
|
76
|
+
nodes.push(
|
|
77
|
+
{
|
|
78
|
+
kind: "text",
|
|
79
|
+
key: `${id}:name:${key}`,
|
|
80
|
+
role: "label",
|
|
81
|
+
x: slice.x,
|
|
82
|
+
y: plot.y,
|
|
83
|
+
text: series.label ?? context.formatX(category),
|
|
84
|
+
paint: {
|
|
85
|
+
fill: theme.muted,
|
|
86
|
+
fontSize: theme.fontSize,
|
|
87
|
+
baseline: "top"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
kind: "text",
|
|
92
|
+
key: `${id}:value:${key}`,
|
|
93
|
+
role: "label",
|
|
94
|
+
x: slice.x,
|
|
95
|
+
y: plot.y + theme.fontSize + 4,
|
|
96
|
+
text: context.formatY(slice.value),
|
|
97
|
+
paint: {
|
|
98
|
+
fill: theme.foreground,
|
|
99
|
+
fontSize: theme.fontSize + 2,
|
|
100
|
+
fontWeight: 600,
|
|
101
|
+
baseline: "top"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
if (options.tip === false) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const previous = slice.index > 0 ? values[slice.index - 1] : void 0;
|
|
110
|
+
const conversion = previous !== void 0 && previous > 0 ? ` (${formatPercentage(slice.value / previous, context.locale)})` : "";
|
|
111
|
+
const centerY = top + height / 2;
|
|
112
|
+
points.push({
|
|
113
|
+
key: `${id}:${key}`,
|
|
114
|
+
markId: id,
|
|
115
|
+
index: slice.index,
|
|
116
|
+
datum: data[slice.index],
|
|
117
|
+
x: slice.x + slice.width / 2,
|
|
118
|
+
y: centerY,
|
|
119
|
+
xValue: category,
|
|
120
|
+
yValue: slice.value,
|
|
121
|
+
series: series.key,
|
|
122
|
+
color: series.color,
|
|
123
|
+
title: series.label ?? context.formatX(category),
|
|
124
|
+
value: `${context.formatY(slice.value)}${conversion}`,
|
|
125
|
+
hit: {
|
|
126
|
+
kind: "rect",
|
|
127
|
+
rect: {
|
|
128
|
+
x: slice.x,
|
|
129
|
+
y: centerY - slice.leftHeight / 2,
|
|
130
|
+
width: slice.width,
|
|
131
|
+
height: slice.leftHeight
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return { nodes, points };
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
export {
|
|
141
|
+
funnel
|
|
142
|
+
};
|
|
143
|
+
//# sourceMappingURL=funnel.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/core/marks/funnel.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n\tchannelLabel,\n\tisPlaceable,\n\tnumericValue,\n\treadChannel,\n} from \"#/core/channel.ts\";\nimport { formatPercentage } from \"#/core/format.ts\";\nimport { funnelSlices } from \"#/core/marks/funnel-layout.ts\";\nimport {\n\ttype ChartMarkOptions,\n\tmarkId,\n\tpaint,\n\tseriesResolver,\n} from \"#/core/marks/shared.ts\";\nimport { categoryKey } from \"#/core/scales/discrete.ts\";\nimport type {\n\tChartAccessor,\n\tChartMark,\n\tChartPoint,\n\tChartValue,\n\tSceneNode,\n} from \"#/core/types.ts\";\n\nexport interface FunnelOptions<TDatum> extends ChartMarkOptions<TDatum> {\n\t/** The step: \"Visites\", \"Inscriptions\", \"Missions\". */\n\treadonly category: ChartAccessor<TDatum, ChartValue>;\n\treadonly value: ChartAccessor<TDatum, ChartValue>;\n\t/** Pixels of blank between two steps. */\n\treadonly gap?: number;\n\treadonly fill?: string;\n\t/** `false` drops the step name and value written above each step. */\n\treadonly labels?: boolean;\n}\n\n/** Room kept above the shape for each step's name and value. */\nconst LABEL_ZONE = 36;\n\n/**\n * Steps left to right, each as tall as its value, each sloping down to the\n * next: the drop between two stages is the shape itself. The tooltip gives\n * the conversion from the step before.\n */\nexport function funnel<TDatum>(\n\tdata: ReadonlyArray<TDatum>,\n\toptions: FunnelOptions<TDatum>,\n): ChartMark {\n\tconst categories = readChannel(data, options.category);\n\tconst values = readChannel(data, options.value).map(\n\t\t(value) => numericValue(value) ?? 0,\n\t);\n\tconst colorAccessor = options.color ?? options.category;\n\tconst colors = readChannel(data, colorAccessor);\n\treturn {\n\t\tid: options.id,\n\t\tcoordinate: \"frame\",\n\t\tfocusOrder: \"point\",\n\t\tcolorLegend: options.labels === false,\n\t\ttitles: {\n\t\t\tcategory: channelLabel(options.category),\n\t\t\tvalue: channelLabel(options.value) ?? options.label,\n\t\t},\n\t\tchannels: {\n\t\t\tcolor: {\n\t\t\t\tvalues: colors.filter(isPlaceable),\n\t\t\t\tlabel: channelLabel(colorAccessor),\n\t\t\t},\n\t\t},\n\t\trender(context) {\n\t\t\tconst id = markId(options.id, \"funnel\", context);\n\t\t\tconst { plot, theme } = context;\n\t\t\tconst labelled = options.labels !== false;\n\t\t\tconst top = plot.y + (labelled ? LABEL_ZONE : 0);\n\t\t\tconst height = Math.max(0, plot.height - (labelled ? LABEL_ZONE : 0));\n\t\t\tconst slices = funnelSlices({\n\t\t\t\tvalues,\n\t\t\t\tinnerWidth: plot.width,\n\t\t\t\tinnerHeight: height,\n\t\t\t\tcenterY: top + height / 2,\n\t\t\t\toriginX: plot.x,\n\t\t\t\tgap: options.gap,\n\t\t\t});\n\t\t\tconst seriesOf = seriesResolver(\n\t\t\t\tcolors,\n\t\t\t\t{ ...options, color: colorAccessor, fixedColor: options.fill },\n\t\t\t\tid,\n\t\t\t\tcontext,\n\t\t\t);\n\t\t\tconst nodes: SceneNode[] = [];\n\t\t\tconst points: ChartPoint[] = [];\n\t\t\tfor (const slice of slices) {\n\t\t\t\tconst category = categories[slice.index];\n\t\t\t\tif (!isPlaceable(category) || slice.path === \"\") {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst series = seriesOf(slice.index);\n\t\t\t\tconst key = categoryKey(category);\n\t\t\t\tnodes.push({\n\t\t\t\t\tkind: \"path\",\n\t\t\t\t\tkey: `${id}:${key}`,\n\t\t\t\t\tseries: series.key,\n\t\t\t\t\trole: \"mark\",\n\t\t\t\t\td: slice.path,\n\t\t\t\t\tpaint: paint({ fill: series.color, opacity: options.opacity }),\n\t\t\t\t});\n\t\t\t\tif (labelled) {\n\t\t\t\t\tnodes.push(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tkind: \"text\",\n\t\t\t\t\t\t\tkey: `${id}:name:${key}`,\n\t\t\t\t\t\t\trole: \"label\",\n\t\t\t\t\t\t\tx: slice.x,\n\t\t\t\t\t\t\ty: plot.y,\n\t\t\t\t\t\t\ttext: series.label ?? context.formatX(category),\n\t\t\t\t\t\t\tpaint: {\n\t\t\t\t\t\t\t\tfill: theme.muted,\n\t\t\t\t\t\t\t\tfontSize: theme.fontSize,\n\t\t\t\t\t\t\t\tbaseline: \"top\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tkind: \"text\",\n\t\t\t\t\t\t\tkey: `${id}:value:${key}`,\n\t\t\t\t\t\t\trole: \"label\",\n\t\t\t\t\t\t\tx: slice.x,\n\t\t\t\t\t\t\ty: plot.y + theme.fontSize + 4,\n\t\t\t\t\t\t\ttext: context.formatY(slice.value),\n\t\t\t\t\t\t\tpaint: {\n\t\t\t\t\t\t\t\tfill: theme.foreground,\n\t\t\t\t\t\t\t\tfontSize: theme.fontSize + 2,\n\t\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\t\tbaseline: \"top\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (options.tip === false) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst previous = slice.index > 0 ? values[slice.index - 1] : undefined;\n\t\t\t\tconst conversion =\n\t\t\t\t\tprevious !== undefined && previous > 0\n\t\t\t\t\t\t? ` (${formatPercentage(slice.value / previous, context.locale)})`\n\t\t\t\t\t\t: \"\";\n\t\t\t\tconst centerY = top + height / 2;\n\t\t\t\tpoints.push({\n\t\t\t\t\tkey: `${id}:${key}`,\n\t\t\t\t\tmarkId: id,\n\t\t\t\t\tindex: slice.index,\n\t\t\t\t\tdatum: data[slice.index],\n\t\t\t\t\tx: slice.x + slice.width / 2,\n\t\t\t\t\ty: centerY,\n\t\t\t\t\txValue: category,\n\t\t\t\t\tyValue: slice.value,\n\t\t\t\t\tseries: series.key,\n\t\t\t\t\tcolor: series.color,\n\t\t\t\t\ttitle: series.label ?? context.formatX(category),\n\t\t\t\t\tvalue: `${context.formatY(slice.value)}${conversion}`,\n\t\t\t\t\thit: {\n\t\t\t\t\t\tkind: \"rect\",\n\t\t\t\t\t\trect: {\n\t\t\t\t\t\t\tx: slice.x,\n\t\t\t\t\t\t\ty: centerY - slice.leftHeight / 2,\n\t\t\t\t\t\t\twidth: slice.width,\n\t\t\t\t\t\t\theight: slice.leftHeight,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { nodes, points };\n\t\t},\n\t};\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ChartMarkOptions } from "./shared.js";
|
|
2
|
+
import type { ChartAccessor, ChartCurve, ChartMark, ChartValue } from "../types.js";
|
|
3
|
+
export interface LineOptions<TDatum> extends ChartMarkOptions<TDatum> {
|
|
4
|
+
readonly x?: ChartAccessor<TDatum, ChartValue>;
|
|
5
|
+
readonly y?: ChartAccessor<TDatum, ChartValue>;
|
|
6
|
+
readonly stroke?: string;
|
|
7
|
+
readonly strokeWidth?: number;
|
|
8
|
+
readonly strokeDasharray?: string;
|
|
9
|
+
readonly curve?: ChartCurve;
|
|
10
|
+
/** A dot on every point, not only on the focused one. */
|
|
11
|
+
readonly dots?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/** A line whose value runs up the y axis, over x positions: a time series. */
|
|
14
|
+
export declare function lineY<TDatum>(data: ReadonlyArray<TDatum>, options?: LineOptions<TDatum>): ChartMark;
|
|
15
|
+
/** A line whose value runs along x, over y positions. */
|
|
16
|
+
export declare function lineX<TDatum>(data: ReadonlyArray<TDatum>, options?: LineOptions<TDatum>): ChartMark;
|
|
17
|
+
//# sourceMappingURL=line.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"line.d.ts","sourceRoot":"","sources":["../../../src/core/marks/line.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,gBAAgB,EAOrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EACX,aAAa,EACb,UAAU,EACV,SAAS,EAET,UAAU,EAEV,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,WAAW,CAAC,MAAM,CAAE,SAAQ,gBAAgB,CAAC,MAAM,CAAC;IACpE,QAAQ,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/C,QAAQ,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,yDAAyD;IACzD,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACxB;AAkKD,8EAA8E;AAC9E,wBAAgB,KAAK,CAAC,MAAM,EAC3B,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAC3B,OAAO,GAAE,WAAW,CAAC,MAAM,CAAM,GAC/B,SAAS,CAEX;AAED,yDAAyD;AACzD,wBAAgB,KAAK,CAAC,MAAM,EAC3B,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAC3B,OAAO,GAAE,WAAW,CAAC,MAAM,CAAM,GAC/B,SAAS,CAEX"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { channelLabel, isPlaceable, readChannel } from "../channel.js";
|
|
2
|
+
import {
|
|
3
|
+
colorChannel,
|
|
4
|
+
groupBySeries,
|
|
5
|
+
markId,
|
|
6
|
+
paint,
|
|
7
|
+
seriesResolver,
|
|
8
|
+
valueOn
|
|
9
|
+
} from "./shared.js";
|
|
10
|
+
import { linePath } from "../paths.js";
|
|
11
|
+
const DEFAULT_STROKE_WIDTH = 2;
|
|
12
|
+
const DOT_RADIUS = 3;
|
|
13
|
+
function positionAccessor(accessor, fallback) {
|
|
14
|
+
if (accessor !== void 0) {
|
|
15
|
+
return accessor;
|
|
16
|
+
}
|
|
17
|
+
return fallback === "index" ? (_datum, index) => index : (datum) => datum;
|
|
18
|
+
}
|
|
19
|
+
function lineMark(kind, data, options) {
|
|
20
|
+
const vertical = kind === "lineY";
|
|
21
|
+
const positionKey = vertical ? options.x : options.y;
|
|
22
|
+
const valueKey = vertical ? options.y : options.x;
|
|
23
|
+
const positions = readChannel(data, positionAccessor(positionKey, "index"));
|
|
24
|
+
const values = readChannel(data, positionAccessor(valueKey, "identity"));
|
|
25
|
+
const colors = colorChannel(data, options);
|
|
26
|
+
const positionChannel = {
|
|
27
|
+
values: positions.filter(isPlaceable),
|
|
28
|
+
label: channelLabel(positionKey)
|
|
29
|
+
};
|
|
30
|
+
const valueChannel = {
|
|
31
|
+
values: values.filter(isPlaceable),
|
|
32
|
+
label: channelLabel(valueKey) ?? options.label
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
id: options.id,
|
|
36
|
+
coordinate: "cartesian",
|
|
37
|
+
focusOrder: vertical ? "x" : "y",
|
|
38
|
+
channels: {
|
|
39
|
+
x: vertical ? positionChannel : valueChannel,
|
|
40
|
+
y: vertical ? valueChannel : positionChannel,
|
|
41
|
+
color: colors.channel
|
|
42
|
+
},
|
|
43
|
+
render(context) {
|
|
44
|
+
const id = markId(options.id, kind, context);
|
|
45
|
+
const positionScale = vertical ? context.scales.x : context.scales.y;
|
|
46
|
+
const valueScale = vertical ? context.scales.y : context.scales.x;
|
|
47
|
+
if (positionScale === void 0 || valueScale === void 0) {
|
|
48
|
+
return { nodes: [] };
|
|
49
|
+
}
|
|
50
|
+
const seriesOf = seriesResolver(
|
|
51
|
+
colors.values,
|
|
52
|
+
{ ...options, fixedColor: options.stroke },
|
|
53
|
+
id,
|
|
54
|
+
context
|
|
55
|
+
);
|
|
56
|
+
const lines = [];
|
|
57
|
+
const dots = [];
|
|
58
|
+
const points = [];
|
|
59
|
+
for (const { series, indices } of groupBySeries(
|
|
60
|
+
data.length,
|
|
61
|
+
seriesOf
|
|
62
|
+
).values()) {
|
|
63
|
+
const runs = [[]];
|
|
64
|
+
for (const index of indices) {
|
|
65
|
+
const position = positions[index];
|
|
66
|
+
const value = valueOn(valueScale, values[index]);
|
|
67
|
+
if (!isPlaceable(position) || value === void 0) {
|
|
68
|
+
runs.push([]);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const along = positionScale.center(position);
|
|
72
|
+
const across = valueScale.center(value);
|
|
73
|
+
const xy = vertical ? { x: along, y: across } : { x: across, y: along };
|
|
74
|
+
runs[runs.length - 1].push(xy);
|
|
75
|
+
if (options.tip !== false) {
|
|
76
|
+
points.push({
|
|
77
|
+
key: `${id}:${index}`,
|
|
78
|
+
markId: id,
|
|
79
|
+
index,
|
|
80
|
+
datum: data[index],
|
|
81
|
+
x: xy.x,
|
|
82
|
+
y: xy.y,
|
|
83
|
+
xValue: vertical ? position : value,
|
|
84
|
+
yValue: vertical ? value : position,
|
|
85
|
+
series: series.key,
|
|
86
|
+
seriesLabel: series.label,
|
|
87
|
+
color: series.color,
|
|
88
|
+
title: vertical ? context.formatX(position) : context.formatY(position),
|
|
89
|
+
value: vertical ? context.formatY(value) : context.formatX(value)
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (options.dots) {
|
|
93
|
+
dots.push({
|
|
94
|
+
kind: "circle",
|
|
95
|
+
key: `${id}:dot:${index}`,
|
|
96
|
+
series: series.key,
|
|
97
|
+
role: "mark",
|
|
98
|
+
cx: xy.x,
|
|
99
|
+
cy: xy.y,
|
|
100
|
+
r: DOT_RADIUS,
|
|
101
|
+
paint: paint({
|
|
102
|
+
fill: series.color,
|
|
103
|
+
stroke: context.theme.background,
|
|
104
|
+
strokeWidth: 1.5,
|
|
105
|
+
opacity: options.opacity
|
|
106
|
+
})
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const d = runs.map((run) => linePath(run, options.curve)).filter((part) => part !== "").join("");
|
|
111
|
+
lines.push({
|
|
112
|
+
kind: "path",
|
|
113
|
+
key: `${id}:line:${series.key}`,
|
|
114
|
+
series: series.key,
|
|
115
|
+
role: "mark",
|
|
116
|
+
d,
|
|
117
|
+
paint: paint({
|
|
118
|
+
stroke: series.color,
|
|
119
|
+
strokeWidth: options.strokeWidth ?? DEFAULT_STROKE_WIDTH,
|
|
120
|
+
strokeDasharray: options.strokeDasharray,
|
|
121
|
+
strokeLinecap: "round",
|
|
122
|
+
strokeLinejoin: "round",
|
|
123
|
+
fill: "none",
|
|
124
|
+
opacity: options.opacity
|
|
125
|
+
})
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
const legend = options.color === void 0 && options.label !== void 0 ? [
|
|
129
|
+
{
|
|
130
|
+
key: id,
|
|
131
|
+
label: options.label,
|
|
132
|
+
color: options.stroke ?? context.paletteColor(context.markIndex),
|
|
133
|
+
shape: options.strokeDasharray ? "dashed" : "line"
|
|
134
|
+
}
|
|
135
|
+
] : [];
|
|
136
|
+
return { nodes: [...lines, ...dots], points, legend };
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function lineY(data, options = {}) {
|
|
141
|
+
return lineMark("lineY", data, options);
|
|
142
|
+
}
|
|
143
|
+
function lineX(data, options = {}) {
|
|
144
|
+
return lineMark("lineX", data, options);
|
|
145
|
+
}
|
|
146
|
+
export {
|
|
147
|
+
lineX,
|
|
148
|
+
lineY
|
|
149
|
+
};
|
|
150
|
+
//# sourceMappingURL=line.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/core/marks/line.ts"],
|
|
4
|
+
"sourcesContent": ["import { channelLabel, isPlaceable, readChannel } from \"#/core/channel.ts\";\nimport {\n\ttype ChartMarkOptions,\n\tcolorChannel,\n\tgroupBySeries,\n\tmarkId,\n\tpaint,\n\tseriesResolver,\n\tvalueOn,\n} from \"#/core/marks/shared.ts\";\nimport { type ChartXY, linePath } from \"#/core/paths.ts\";\nimport type {\n\tChartAccessor,\n\tChartCurve,\n\tChartMark,\n\tChartPoint,\n\tChartValue,\n\tSceneNode,\n} from \"#/core/types.ts\";\n\nexport interface LineOptions<TDatum> extends ChartMarkOptions<TDatum> {\n\treadonly x?: ChartAccessor<TDatum, ChartValue>;\n\treadonly y?: ChartAccessor<TDatum, ChartValue>;\n\treadonly stroke?: string;\n\treadonly strokeWidth?: number;\n\treadonly strokeDasharray?: string;\n\treadonly curve?: ChartCurve;\n\t/** A dot on every point, not only on the focused one. */\n\treadonly dots?: boolean;\n}\n\nconst DEFAULT_STROKE_WIDTH = 2;\nconst DOT_RADIUS = 3;\n\n/** With no accessor, a line of plain numbers plots each against its index. */\nfunction positionAccessor<TDatum>(\n\taccessor: ChartAccessor<TDatum, ChartValue> | undefined,\n\tfallback: \"index\" | \"identity\",\n): ChartAccessor<TDatum, ChartValue> {\n\tif (accessor !== undefined) {\n\t\treturn accessor;\n\t}\n\treturn fallback === \"index\"\n\t\t? (_datum, index) => index\n\t\t: (datum) => datum as unknown as ChartValue;\n}\n\nfunction lineMark<TDatum>(\n\tkind: \"lineY\" | \"lineX\",\n\tdata: ReadonlyArray<TDatum>,\n\toptions: LineOptions<TDatum>,\n): ChartMark {\n\t// lineY: the value runs up the y axis; lineX: along x, positions down y.\n\tconst vertical = kind === \"lineY\";\n\tconst positionKey = vertical ? options.x : options.y;\n\tconst valueKey = vertical ? options.y : options.x;\n\tconst positions = readChannel(data, positionAccessor(positionKey, \"index\"));\n\tconst values = readChannel(data, positionAccessor(valueKey, \"identity\"));\n\tconst colors = colorChannel(data, options);\n\tconst positionChannel = {\n\t\tvalues: positions.filter(isPlaceable),\n\t\tlabel: channelLabel(positionKey),\n\t};\n\tconst valueChannel = {\n\t\tvalues: values.filter(isPlaceable),\n\t\tlabel: channelLabel(valueKey) ?? options.label,\n\t};\n\n\treturn {\n\t\tid: options.id,\n\t\tcoordinate: \"cartesian\",\n\t\tfocusOrder: vertical ? \"x\" : \"y\",\n\t\tchannels: {\n\t\t\tx: vertical ? positionChannel : valueChannel,\n\t\t\ty: vertical ? valueChannel : positionChannel,\n\t\t\tcolor: colors.channel,\n\t\t},\n\t\trender(context) {\n\t\t\tconst id = markId(options.id, kind, context);\n\t\t\tconst positionScale = vertical ? context.scales.x : context.scales.y;\n\t\t\tconst valueScale = vertical ? context.scales.y : context.scales.x;\n\t\t\tif (positionScale === undefined || valueScale === undefined) {\n\t\t\t\treturn { nodes: [] };\n\t\t\t}\n\t\t\tconst seriesOf = seriesResolver(\n\t\t\t\tcolors.values,\n\t\t\t\t{ ...options, fixedColor: options.stroke },\n\t\t\t\tid,\n\t\t\t\tcontext,\n\t\t\t);\n\t\t\tconst lines: SceneNode[] = [];\n\t\t\tconst dots: SceneNode[] = [];\n\t\t\tconst points: ChartPoint[] = [];\n\n\t\t\tfor (const { series, indices } of groupBySeries(\n\t\t\t\tdata.length,\n\t\t\t\tseriesOf,\n\t\t\t).values()) {\n\t\t\t\t// A gap in the data is a gap in the line, not a dive to zero.\n\t\t\t\tconst runs: ChartXY[][] = [[]];\n\t\t\t\tfor (const index of indices) {\n\t\t\t\t\tconst position = positions[index];\n\t\t\t\t\tconst value = valueOn(valueScale, values[index]);\n\t\t\t\t\tif (!isPlaceable(position) || value === undefined) {\n\t\t\t\t\t\truns.push([]);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst along = positionScale.center(position);\n\t\t\t\t\tconst across = valueScale.center(value);\n\t\t\t\t\tconst xy = vertical\n\t\t\t\t\t\t? { x: along, y: across }\n\t\t\t\t\t\t: { x: across, y: along };\n\t\t\t\t\truns[runs.length - 1].push(xy);\n\t\t\t\t\tif (options.tip !== false) {\n\t\t\t\t\t\tpoints.push({\n\t\t\t\t\t\t\tkey: `${id}:${index}`,\n\t\t\t\t\t\t\tmarkId: id,\n\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\tdatum: data[index],\n\t\t\t\t\t\t\tx: xy.x,\n\t\t\t\t\t\t\ty: xy.y,\n\t\t\t\t\t\t\txValue: vertical ? position : value,\n\t\t\t\t\t\t\tyValue: vertical ? value : position,\n\t\t\t\t\t\t\tseries: series.key,\n\t\t\t\t\t\t\tseriesLabel: series.label,\n\t\t\t\t\t\t\tcolor: series.color,\n\t\t\t\t\t\t\ttitle: vertical\n\t\t\t\t\t\t\t\t? context.formatX(position)\n\t\t\t\t\t\t\t\t: context.formatY(position),\n\t\t\t\t\t\t\tvalue: vertical ? context.formatY(value) : context.formatX(value),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif (options.dots) {\n\t\t\t\t\t\tdots.push({\n\t\t\t\t\t\t\tkind: \"circle\",\n\t\t\t\t\t\t\tkey: `${id}:dot:${index}`,\n\t\t\t\t\t\t\tseries: series.key,\n\t\t\t\t\t\t\trole: \"mark\",\n\t\t\t\t\t\t\tcx: xy.x,\n\t\t\t\t\t\t\tcy: xy.y,\n\t\t\t\t\t\t\tr: DOT_RADIUS,\n\t\t\t\t\t\t\tpaint: paint({\n\t\t\t\t\t\t\t\tfill: series.color,\n\t\t\t\t\t\t\t\tstroke: context.theme.background,\n\t\t\t\t\t\t\t\tstrokeWidth: 1.5,\n\t\t\t\t\t\t\t\topacity: options.opacity,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst d = runs\n\t\t\t\t\t.map((run) => linePath(run, options.curve))\n\t\t\t\t\t.filter((part) => part !== \"\")\n\t\t\t\t\t.join(\"\");\n\t\t\t\tlines.push({\n\t\t\t\t\tkind: \"path\",\n\t\t\t\t\tkey: `${id}:line:${series.key}`,\n\t\t\t\t\tseries: series.key,\n\t\t\t\t\trole: \"mark\",\n\t\t\t\t\td,\n\t\t\t\t\tpaint: paint({\n\t\t\t\t\t\tstroke: series.color,\n\t\t\t\t\t\tstrokeWidth: options.strokeWidth ?? DEFAULT_STROKE_WIDTH,\n\t\t\t\t\t\tstrokeDasharray: options.strokeDasharray,\n\t\t\t\t\t\tstrokeLinecap: \"round\",\n\t\t\t\t\t\tstrokeLinejoin: \"round\",\n\t\t\t\t\t\tfill: \"none\",\n\t\t\t\t\t\topacity: options.opacity,\n\t\t\t\t\t}),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst legend =\n\t\t\t\toptions.color === undefined && options.label !== undefined\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkey: id,\n\t\t\t\t\t\t\t\tlabel: options.label,\n\t\t\t\t\t\t\t\tcolor:\n\t\t\t\t\t\t\t\t\toptions.stroke ?? context.paletteColor(context.markIndex),\n\t\t\t\t\t\t\t\tshape: options.strokeDasharray\n\t\t\t\t\t\t\t\t\t? (\"dashed\" as const)\n\t\t\t\t\t\t\t\t\t: (\"line\" as const),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]\n\t\t\t\t\t: [];\n\t\t\treturn { nodes: [...lines, ...dots], points, legend };\n\t\t},\n\t};\n}\n\n/** A line whose value runs up the y axis, over x positions: a time series. */\nexport function lineY<TDatum>(\n\tdata: ReadonlyArray<TDatum>,\n\toptions: LineOptions<TDatum> = {},\n): ChartMark {\n\treturn lineMark(\"lineY\", data, options);\n}\n\n/** A line whose value runs along x, over y positions. */\nexport function lineX<TDatum>(\n\tdata: ReadonlyArray<TDatum>,\n\toptions: LineOptions<TDatum> = {},\n): ChartMark {\n\treturn lineMark(\"lineX\", data, options);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type ChartMarkOptions } from "./shared.js";
|
|
2
|
+
import type { ChartAccessor, ChartMark, ChartValue } from "../types.js";
|
|
3
|
+
interface SliceAngle {
|
|
4
|
+
readonly startAngle: number;
|
|
5
|
+
readonly endAngle: number;
|
|
6
|
+
readonly fraction: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Splits a turn between values, proportionally. Negative values count as
|
|
10
|
+
* zero: a pie of signed numbers has no honest reading.
|
|
11
|
+
*/
|
|
12
|
+
export declare function sliceAngles(values: ReadonlyArray<number>, padAngle?: number, startAngle?: number, endAngle?: number): ReadonlyArray<SliceAngle>;
|
|
13
|
+
export interface ArcOptions<TDatum> extends ChartMarkOptions<TDatum> {
|
|
14
|
+
/** The slice's name: what the legend, tooltip and table call it. */
|
|
15
|
+
readonly category: ChartAccessor<TDatum, ChartValue>;
|
|
16
|
+
readonly value: ChartAccessor<TDatum, ChartValue>;
|
|
17
|
+
/** Share of the radius left empty in the middle: 0 is a pie, 0.6 a donut. */
|
|
18
|
+
readonly innerRadius?: number;
|
|
19
|
+
/** Degrees of blank between two slices. */
|
|
20
|
+
readonly padAngle?: number;
|
|
21
|
+
readonly startAngle?: number;
|
|
22
|
+
readonly endAngle?: number;
|
|
23
|
+
readonly fill?: string;
|
|
24
|
+
readonly stroke?: string;
|
|
25
|
+
}
|
|
26
|
+
/** A pie, or a donut with `innerRadius`: each datum a slice of the whole. */
|
|
27
|
+
export declare function arc<TDatum>(data: ReadonlyArray<TDatum>, options: ArcOptions<TDatum>): ChartMark;
|
|
28
|
+
/** A ring of slices: `arc` with the middle left empty. */
|
|
29
|
+
export declare function donut<TDatum>(data: ReadonlyArray<TDatum>, options: ArcOptions<TDatum>): ChartMark;
|
|
30
|
+
export interface RadialBarOptions<TDatum> extends ChartMarkOptions<TDatum> {
|
|
31
|
+
readonly category: ChartAccessor<TDatum, ChartValue>;
|
|
32
|
+
readonly value: ChartAccessor<TDatum, ChartValue>;
|
|
33
|
+
/** The value a full turn stands for. Defaults to the largest value, rounded up. */
|
|
34
|
+
readonly max?: number;
|
|
35
|
+
/** Share of the radius left empty in the middle. */
|
|
36
|
+
readonly innerRadius?: number;
|
|
37
|
+
/** Share of each ring's thickness left empty between two rings. */
|
|
38
|
+
readonly gap?: number;
|
|
39
|
+
/** Draw each ring's empty remainder, so the bars read against a full turn. */
|
|
40
|
+
readonly track?: boolean;
|
|
41
|
+
readonly fill?: string;
|
|
42
|
+
}
|
|
43
|
+
/** Concentric rings, each filled as far round as its value: progress against a common maximum. */
|
|
44
|
+
export declare function radialBar<TDatum>(data: ReadonlyArray<TDatum>, options: RadialBarOptions<TDatum>): ChartMark;
|
|
45
|
+
export interface RadarOptions<TDatum> extends ChartMarkOptions<TDatum> {
|
|
46
|
+
/** The spoke a value sits on: "Vitesse", "Endurance"… */
|
|
47
|
+
readonly axis: ChartAccessor<TDatum, ChartValue>;
|
|
48
|
+
readonly value: ChartAccessor<TDatum, ChartValue>;
|
|
49
|
+
/** The value the outer ring stands for. Defaults to the largest value, rounded up. */
|
|
50
|
+
readonly max?: number;
|
|
51
|
+
/** Grid rings between the centre and the outer ring. */
|
|
52
|
+
readonly rings?: number;
|
|
53
|
+
readonly fillOpacity?: number;
|
|
54
|
+
readonly fill?: string;
|
|
55
|
+
/** `false` leaves the grid and spoke labels to another radar on the same chart. */
|
|
56
|
+
readonly grid?: boolean;
|
|
57
|
+
}
|
|
58
|
+
/** Values on spokes joined into a polygon, one per series: profiles compared at a glance. */
|
|
59
|
+
export declare function radar<TDatum>(data: ReadonlyArray<TDatum>, options: RadarOptions<TDatum>): ChartMark;
|
|
60
|
+
export {};
|
|
61
|
+
//# sourceMappingURL=polar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polar.d.ts","sourceRoot":"","sources":["../../../src/core/marks/polar.ts"],"names":[],"mappings":"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"}
|