@adminiumjs/charts 0.1.0-rc.1
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/LICENSE +661 -0
- package/dist/components/AnomalyChart.d.ts +30 -0
- package/dist/components/AnomalyChart.d.ts.map +1 -0
- package/dist/components/AnomalyChart.js +32 -0
- package/dist/components/AnomalyChart.js.map +1 -0
- package/dist/components/BarChart.d.ts +33 -0
- package/dist/components/BarChart.d.ts.map +1 -0
- package/dist/components/BarChart.js +40 -0
- package/dist/components/BarChart.js.map +1 -0
- package/dist/components/BoxPlotChart.d.ts +23 -0
- package/dist/components/BoxPlotChart.d.ts.map +1 -0
- package/dist/components/BoxPlotChart.js +24 -0
- package/dist/components/BoxPlotChart.js.map +1 -0
- package/dist/components/BulletChart.d.ts +27 -0
- package/dist/components/BulletChart.d.ts.map +1 -0
- package/dist/components/BulletChart.js +24 -0
- package/dist/components/BulletChart.js.map +1 -0
- package/dist/components/BumpChart.d.ts +27 -0
- package/dist/components/BumpChart.d.ts.map +1 -0
- package/dist/components/BumpChart.js +17 -0
- package/dist/components/BumpChart.js.map +1 -0
- package/dist/components/CandlestickChart.d.ts +26 -0
- package/dist/components/CandlestickChart.d.ts.map +1 -0
- package/dist/components/CandlestickChart.js +22 -0
- package/dist/components/CandlestickChart.js.map +1 -0
- package/dist/components/ChartSurface.d.ts +52 -0
- package/dist/components/ChartSurface.d.ts.map +1 -0
- package/dist/components/ChartSurface.js +15 -0
- package/dist/components/ChartSurface.js.map +1 -0
- package/dist/components/Chord.d.ts +30 -0
- package/dist/components/Chord.d.ts.map +1 -0
- package/dist/components/Chord.js +14 -0
- package/dist/components/Chord.js.map +1 -0
- package/dist/components/ChoroplethGridChart.d.ts +32 -0
- package/dist/components/ChoroplethGridChart.d.ts.map +1 -0
- package/dist/components/ChoroplethGridChart.js +15 -0
- package/dist/components/ChoroplethGridChart.js.map +1 -0
- package/dist/components/CohortMatrixChart.d.ts +30 -0
- package/dist/components/CohortMatrixChart.d.ts.map +1 -0
- package/dist/components/CohortMatrixChart.js +13 -0
- package/dist/components/CohortMatrixChart.js.map +1 -0
- package/dist/components/CorrelationMatrixChart.d.ts +24 -0
- package/dist/components/CorrelationMatrixChart.d.ts.map +1 -0
- package/dist/components/CorrelationMatrixChart.js +29 -0
- package/dist/components/CorrelationMatrixChart.js.map +1 -0
- package/dist/components/DonutChart.d.ts +31 -0
- package/dist/components/DonutChart.d.ts.map +1 -0
- package/dist/components/DonutChart.js +19 -0
- package/dist/components/DonutChart.js.map +1 -0
- package/dist/components/ForecastChart.d.ts +37 -0
- package/dist/components/ForecastChart.d.ts.map +1 -0
- package/dist/components/ForecastChart.js +39 -0
- package/dist/components/ForecastChart.js.map +1 -0
- package/dist/components/Funnel.d.ts +27 -0
- package/dist/components/Funnel.d.ts.map +1 -0
- package/dist/components/Funnel.js +25 -0
- package/dist/components/Funnel.js.map +1 -0
- package/dist/components/HeatCalendarChart.d.ts +39 -0
- package/dist/components/HeatCalendarChart.d.ts.map +1 -0
- package/dist/components/HeatCalendarChart.js +37 -0
- package/dist/components/HeatCalendarChart.js.map +1 -0
- package/dist/components/HeatMonthChart.d.ts +30 -0
- package/dist/components/HeatMonthChart.d.ts.map +1 -0
- package/dist/components/HeatMonthChart.js +14 -0
- package/dist/components/HeatMonthChart.js.map +1 -0
- package/dist/components/HexbinChart.d.ts +22 -0
- package/dist/components/HexbinChart.d.ts.map +1 -0
- package/dist/components/HexbinChart.js +31 -0
- package/dist/components/HexbinChart.js.map +1 -0
- package/dist/components/LineAreaChart.d.ts +26 -0
- package/dist/components/LineAreaChart.d.ts.map +1 -0
- package/dist/components/LineAreaChart.js +62 -0
- package/dist/components/LineAreaChart.js.map +1 -0
- package/dist/components/MarimekkoChart.d.ts +24 -0
- package/dist/components/MarimekkoChart.d.ts.map +1 -0
- package/dist/components/MarimekkoChart.js +20 -0
- package/dist/components/MarimekkoChart.js.map +1 -0
- package/dist/components/MultiLineChart.d.ts +36 -0
- package/dist/components/MultiLineChart.d.ts.map +1 -0
- package/dist/components/MultiLineChart.js +62 -0
- package/dist/components/MultiLineChart.js.map +1 -0
- package/dist/components/ParallelCoordinatesChart.d.ts +22 -0
- package/dist/components/ParallelCoordinatesChart.d.ts.map +1 -0
- package/dist/components/ParallelCoordinatesChart.js +16 -0
- package/dist/components/ParallelCoordinatesChart.js.map +1 -0
- package/dist/components/ParetoChart.d.ts +26 -0
- package/dist/components/ParetoChart.d.ts.map +1 -0
- package/dist/components/ParetoChart.js +26 -0
- package/dist/components/ParetoChart.js.map +1 -0
- package/dist/components/Radar.d.ts +27 -0
- package/dist/components/Radar.d.ts.map +1 -0
- package/dist/components/Radar.js +19 -0
- package/dist/components/Radar.js.map +1 -0
- package/dist/components/RadialBar.d.ts +25 -0
- package/dist/components/RadialBar.d.ts.map +1 -0
- package/dist/components/RadialBar.js +12 -0
- package/dist/components/RadialBar.js.map +1 -0
- package/dist/components/RankingBars.d.ts +27 -0
- package/dist/components/RankingBars.d.ts.map +1 -0
- package/dist/components/RankingBars.js +25 -0
- package/dist/components/RankingBars.js.map +1 -0
- package/dist/components/RidgelineChart.d.ts +23 -0
- package/dist/components/RidgelineChart.d.ts.map +1 -0
- package/dist/components/RidgelineChart.js +20 -0
- package/dist/components/RidgelineChart.js.map +1 -0
- package/dist/components/SankeyChart.d.ts +29 -0
- package/dist/components/SankeyChart.d.ts.map +1 -0
- package/dist/components/SankeyChart.js +21 -0
- package/dist/components/SankeyChart.js.map +1 -0
- package/dist/components/ScatterBubbleChart.d.ts +26 -0
- package/dist/components/ScatterBubbleChart.d.ts.map +1 -0
- package/dist/components/ScatterBubbleChart.js +31 -0
- package/dist/components/ScatterBubbleChart.js.map +1 -0
- package/dist/components/SlopeChart.d.ts +28 -0
- package/dist/components/SlopeChart.d.ts.map +1 -0
- package/dist/components/SlopeChart.js +18 -0
- package/dist/components/SlopeChart.js.map +1 -0
- package/dist/components/Sparkline.d.ts +15 -0
- package/dist/components/Sparkline.d.ts.map +1 -0
- package/dist/components/Sparkline.js +27 -0
- package/dist/components/Sparkline.js.map +1 -0
- package/dist/components/StackedBar100.d.ts +30 -0
- package/dist/components/StackedBar100.d.ts.map +1 -0
- package/dist/components/StackedBar100.js +21 -0
- package/dist/components/StackedBar100.js.map +1 -0
- package/dist/components/StreamChart.d.ts +23 -0
- package/dist/components/StreamChart.d.ts.map +1 -0
- package/dist/components/StreamChart.js +56 -0
- package/dist/components/StreamChart.js.map +1 -0
- package/dist/components/Sunburst.d.ts +24 -0
- package/dist/components/Sunburst.d.ts.map +1 -0
- package/dist/components/Sunburst.js +13 -0
- package/dist/components/Sunburst.js.map +1 -0
- package/dist/components/TimelineLanesChart.d.ts +25 -0
- package/dist/components/TimelineLanesChart.d.ts.map +1 -0
- package/dist/components/TimelineLanesChart.js +41 -0
- package/dist/components/TimelineLanesChart.js.map +1 -0
- package/dist/components/Treemap.d.ts +28 -0
- package/dist/components/Treemap.d.ts.map +1 -0
- package/dist/components/Treemap.js +22 -0
- package/dist/components/Treemap.js.map +1 -0
- package/dist/components/ViolinChart.d.ts +22 -0
- package/dist/components/ViolinChart.d.ts.map +1 -0
- package/dist/components/ViolinChart.js +21 -0
- package/dist/components/ViolinChart.js.map +1 -0
- package/dist/components/WaterfallChart.d.ts +23 -0
- package/dist/components/WaterfallChart.d.ts.map +1 -0
- package/dist/components/WaterfallChart.js +29 -0
- package/dist/components/WaterfallChart.js.map +1 -0
- package/dist/components/WordCloud.d.ts +24 -0
- package/dist/components/WordCloud.d.ts.map +1 -0
- package/dist/components/WordCloud.js +22 -0
- package/dist/components/WordCloud.js.map +1 -0
- package/dist/demo/barsRanking.d.ts +26 -0
- package/dist/demo/barsRanking.d.ts.map +1 -0
- package/dist/demo/barsRanking.js +80 -0
- package/dist/demo/barsRanking.js.map +1 -0
- package/dist/demo/generators.d.ts +44 -0
- package/dist/demo/generators.d.ts.map +1 -0
- package/dist/demo/generators.js +72 -0
- package/dist/demo/generators.js.map +1 -0
- package/dist/demo/mulberry32.d.ts +10 -0
- package/dist/demo/mulberry32.d.ts.map +1 -0
- package/dist/demo/mulberry32.js +26 -0
- package/dist/demo/mulberry32.js.map +1 -0
- package/dist/geometry/anomaly.d.ts +22 -0
- package/dist/geometry/anomaly.d.ts.map +1 -0
- package/dist/geometry/anomaly.js +52 -0
- package/dist/geometry/anomaly.js.map +1 -0
- package/dist/geometry/bars.d.ts +46 -0
- package/dist/geometry/bars.d.ts.map +1 -0
- package/dist/geometry/bars.js +68 -0
- package/dist/geometry/bars.js.map +1 -0
- package/dist/geometry/bullet.d.ts +53 -0
- package/dist/geometry/bullet.d.ts.map +1 -0
- package/dist/geometry/bullet.js +67 -0
- package/dist/geometry/bullet.js.map +1 -0
- package/dist/geometry/bump.d.ts +42 -0
- package/dist/geometry/bump.d.ts.map +1 -0
- package/dist/geometry/bump.js +29 -0
- package/dist/geometry/bump.js.map +1 -0
- package/dist/geometry/candles.d.ts +39 -0
- package/dist/geometry/candles.d.ts.map +1 -0
- package/dist/geometry/candles.js +42 -0
- package/dist/geometry/candles.js.map +1 -0
- package/dist/geometry/chord.d.ts +53 -0
- package/dist/geometry/chord.d.ts.map +1 -0
- package/dist/geometry/chord.js +111 -0
- package/dist/geometry/chord.js.map +1 -0
- package/dist/geometry/choropleth.d.ts +58 -0
- package/dist/geometry/choropleth.d.ts.map +1 -0
- package/dist/geometry/choropleth.js +101 -0
- package/dist/geometry/choropleth.js.map +1 -0
- package/dist/geometry/cohort.d.ts +54 -0
- package/dist/geometry/cohort.d.ts.map +1 -0
- package/dist/geometry/cohort.js +70 -0
- package/dist/geometry/cohort.js.map +1 -0
- package/dist/geometry/correlation.d.ts +138 -0
- package/dist/geometry/correlation.d.ts.map +1 -0
- package/dist/geometry/correlation.js +161 -0
- package/dist/geometry/correlation.js.map +1 -0
- package/dist/geometry/distribution.d.ts +115 -0
- package/dist/geometry/distribution.d.ts.map +1 -0
- package/dist/geometry/distribution.js +131 -0
- package/dist/geometry/distribution.js.map +1 -0
- package/dist/geometry/donut.d.ts +37 -0
- package/dist/geometry/donut.d.ts.map +1 -0
- package/dist/geometry/donut.js +46 -0
- package/dist/geometry/donut.js.map +1 -0
- package/dist/geometry/forecast.d.ts +30 -0
- package/dist/geometry/forecast.d.ts.map +1 -0
- package/dist/geometry/forecast.js +75 -0
- package/dist/geometry/forecast.js.map +1 -0
- package/dist/geometry/funnel.d.ts +37 -0
- package/dist/geometry/funnel.d.ts.map +1 -0
- package/dist/geometry/funnel.js +42 -0
- package/dist/geometry/funnel.js.map +1 -0
- package/dist/geometry/heat.d.ts +34 -0
- package/dist/geometry/heat.d.ts.map +1 -0
- package/dist/geometry/heat.js +50 -0
- package/dist/geometry/heat.js.map +1 -0
- package/dist/geometry/heatCalendar.d.ts +43 -0
- package/dist/geometry/heatCalendar.d.ts.map +1 -0
- package/dist/geometry/heatCalendar.js +82 -0
- package/dist/geometry/heatCalendar.js.map +1 -0
- package/dist/geometry/heatMonth.d.ts +47 -0
- package/dist/geometry/heatMonth.d.ts.map +1 -0
- package/dist/geometry/heatMonth.js +72 -0
- package/dist/geometry/heatMonth.js.map +1 -0
- package/dist/geometry/lineArea.d.ts +17 -0
- package/dist/geometry/lineArea.d.ts.map +1 -0
- package/dist/geometry/lineArea.js +37 -0
- package/dist/geometry/lineArea.js.map +1 -0
- package/dist/geometry/marimekko.d.ts +43 -0
- package/dist/geometry/marimekko.d.ts.map +1 -0
- package/dist/geometry/marimekko.js +45 -0
- package/dist/geometry/marimekko.js.map +1 -0
- package/dist/geometry/multiLine.d.ts +19 -0
- package/dist/geometry/multiLine.d.ts.map +1 -0
- package/dist/geometry/multiLine.js +25 -0
- package/dist/geometry/multiLine.js.map +1 -0
- package/dist/geometry/pareto.d.ts +44 -0
- package/dist/geometry/pareto.d.ts.map +1 -0
- package/dist/geometry/pareto.js +65 -0
- package/dist/geometry/pareto.js.map +1 -0
- package/dist/geometry/radar.d.ts +60 -0
- package/dist/geometry/radar.d.ts.map +1 -0
- package/dist/geometry/radar.js +67 -0
- package/dist/geometry/radar.js.map +1 -0
- package/dist/geometry/radialBar.d.ts +31 -0
- package/dist/geometry/radialBar.d.ts.map +1 -0
- package/dist/geometry/radialBar.js +53 -0
- package/dist/geometry/radialBar.js.map +1 -0
- package/dist/geometry/ranking.d.ts +48 -0
- package/dist/geometry/ranking.d.ts.map +1 -0
- package/dist/geometry/ranking.js +42 -0
- package/dist/geometry/ranking.js.map +1 -0
- package/dist/geometry/sankey.d.ts +60 -0
- package/dist/geometry/sankey.d.ts.map +1 -0
- package/dist/geometry/sankey.js +130 -0
- package/dist/geometry/sankey.js.map +1 -0
- package/dist/geometry/scales.d.ts +14 -0
- package/dist/geometry/scales.d.ts.map +1 -0
- package/dist/geometry/scales.js +33 -0
- package/dist/geometry/scales.js.map +1 -0
- package/dist/geometry/slope.d.ts +34 -0
- package/dist/geometry/slope.d.ts.map +1 -0
- package/dist/geometry/slope.js +44 -0
- package/dist/geometry/slope.js.map +1 -0
- package/dist/geometry/sparkline.d.ts +20 -0
- package/dist/geometry/sparkline.d.ts.map +1 -0
- package/dist/geometry/sparkline.js +43 -0
- package/dist/geometry/sparkline.js.map +1 -0
- package/dist/geometry/stacked100.d.ts +33 -0
- package/dist/geometry/stacked100.d.ts.map +1 -0
- package/dist/geometry/stacked100.js +34 -0
- package/dist/geometry/stacked100.js.map +1 -0
- package/dist/geometry/streamStack.d.ts +32 -0
- package/dist/geometry/streamStack.d.ts.map +1 -0
- package/dist/geometry/streamStack.js +56 -0
- package/dist/geometry/streamStack.js.map +1 -0
- package/dist/geometry/sunburst.d.ts +37 -0
- package/dist/geometry/sunburst.d.ts.map +1 -0
- package/dist/geometry/sunburst.js +84 -0
- package/dist/geometry/sunburst.js.map +1 -0
- package/dist/geometry/timelineLanes.d.ts +46 -0
- package/dist/geometry/timelineLanes.d.ts.map +1 -0
- package/dist/geometry/timelineLanes.js +52 -0
- package/dist/geometry/timelineLanes.js.map +1 -0
- package/dist/geometry/treemap.d.ts +42 -0
- package/dist/geometry/treemap.d.ts.map +1 -0
- package/dist/geometry/treemap.js +134 -0
- package/dist/geometry/treemap.js.map +1 -0
- package/dist/geometry/waterfall.d.ts +40 -0
- package/dist/geometry/waterfall.d.ts.map +1 -0
- package/dist/geometry/waterfall.js +80 -0
- package/dist/geometry/waterfall.js.map +1 -0
- package/dist/geometry/wordcloud.d.ts +46 -0
- package/dist/geometry/wordcloud.d.ts.map +1 -0
- package/dist/geometry/wordcloud.js +79 -0
- package/dist/geometry/wordcloud.js.map +1 -0
- package/dist/hooks/useChartSize.d.ts +6 -0
- package/dist/hooks/useChartSize.d.ts.map +1 -0
- package/dist/hooks/useChartSize.js +32 -0
- package/dist/hooks/useChartSize.js.map +1 -0
- package/dist/hooks/useMountAnimation.d.ts +4 -0
- package/dist/hooks/useMountAnimation.d.ts.map +1 -0
- package/dist/hooks/useMountAnimation.js +40 -0
- package/dist/hooks/useMountAnimation.js.map +1 -0
- package/dist/hooks/useRtl.d.ts +7 -0
- package/dist/hooks/useRtl.d.ts.map +1 -0
- package/dist/hooks/useRtl.js +18 -0
- package/dist/hooks/useRtl.js.map +1 -0
- package/dist/index.d.ts +110 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +79 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/format.d.ts +5 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +24 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/stats.d.ts +23 -0
- package/dist/utils/stats.d.ts.map +1 -0
- package/dist/utils/stats.js +82 -0
- package/dist/utils/stats.js.map +1 -0
- package/package.json +36 -0
- package/src/styles.css +205 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** Pure donut geometry — d3-shape pie/arc, maxSlices + "other" bucketing. */
|
|
2
|
+
import { arc, pie } from 'd3-shape';
|
|
3
|
+
/** Aggregate slices beyond `maxSlices` into a trailing "other" bucket. */
|
|
4
|
+
export function bucketSlices(slices, maxSlices, otherLabel = 'Other') {
|
|
5
|
+
if (maxSlices <= 0 || slices.length <= maxSlices) {
|
|
6
|
+
return { slices: [...slices], otherIndex: -1 };
|
|
7
|
+
}
|
|
8
|
+
const kept = slices.slice(0, maxSlices);
|
|
9
|
+
const rest = slices.slice(maxSlices).reduce((sum, s) => sum + s.value, 0);
|
|
10
|
+
return { slices: [...kept, { label: otherLabel, value: rest }], otherIndex: maxSlices };
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Donut arcs in input order (no value sort — legend order matches data).
|
|
14
|
+
* Rotation is always clockwise from 12 o'clock; per the RTL rules
|
|
15
|
+
* (10-i18n-theming.md §5.5) rotation direction does NOT change in RTL — only
|
|
16
|
+
* the surrounding legend/center layout mirrors, which is plain flex/logical CSS.
|
|
17
|
+
*/
|
|
18
|
+
export function donutArcs(slices, options) {
|
|
19
|
+
const { outerRadius, thickness, padAngle = 0.02, cornerRadius = 2, maxSlices = Infinity, otherLabel } = options;
|
|
20
|
+
const bucketed = Number.isFinite(maxSlices)
|
|
21
|
+
? bucketSlices(slices, maxSlices, otherLabel)
|
|
22
|
+
: { slices: [...slices], otherIndex: -1 };
|
|
23
|
+
const total = bucketed.slices.reduce((sum, s) => sum + Math.max(0, s.value), 0);
|
|
24
|
+
if (total <= 0)
|
|
25
|
+
return [];
|
|
26
|
+
const pieLayout = pie()
|
|
27
|
+
.value((d) => Math.max(0, d.value))
|
|
28
|
+
.sort(null)
|
|
29
|
+
.padAngle(padAngle);
|
|
30
|
+
const arcGenerator = arc()
|
|
31
|
+
.innerRadius(Math.max(0, outerRadius - thickness))
|
|
32
|
+
.outerRadius(outerRadius)
|
|
33
|
+
.cornerRadius(cornerRadius);
|
|
34
|
+
return pieLayout(bucketed.slices).map((piece, i) => {
|
|
35
|
+
const isOther = i === bucketed.otherIndex;
|
|
36
|
+
return {
|
|
37
|
+
label: piece.data.label,
|
|
38
|
+
value: piece.data.value,
|
|
39
|
+
share: Math.max(0, piece.data.value) / total,
|
|
40
|
+
path: arcGenerator(piece) ?? '',
|
|
41
|
+
colorVar: isOther ? 'var(--fg-subtle)' : `var(--viz-${(i % 8) + 1})`,
|
|
42
|
+
isOther,
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=donut.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"donut.js","sourceRoot":"","sources":["../../src/geometry/donut.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forecast geometry (`chart-forecast`, research/widget-registry.md §2): a pure
|
|
3
|
+
* linear-projection model plus a closed confidence-polygon path builder. Both
|
|
4
|
+
* are DOM-free and deterministic (04 §7.1). z-multipliers cover the common
|
|
5
|
+
* confidence levels; anything else falls back to the 90% multiplier.
|
|
6
|
+
*/
|
|
7
|
+
import type { XYPoint } from './lineArea.js';
|
|
8
|
+
export declare function zForConfidence(confidence: number): number;
|
|
9
|
+
export interface ForecastModel {
|
|
10
|
+
/** Projected point values, one per horizon step. */
|
|
11
|
+
forecast: number[];
|
|
12
|
+
/** Lower confidence edge per horizon step. */
|
|
13
|
+
lo: number[];
|
|
14
|
+
/** Upper confidence edge per horizon step. */
|
|
15
|
+
hi: number[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Ordinary-least-squares trend over the history indices, projected `horizon`
|
|
19
|
+
* steps forward. The band widens with the square root of the step distance
|
|
20
|
+
* (classic prediction-interval growth), scaled by the in-sample residual
|
|
21
|
+
* standard deviation and the confidence z-multiplier.
|
|
22
|
+
*/
|
|
23
|
+
export declare function linearForecast(history: readonly number[], horizon: number, confidence?: number): ForecastModel;
|
|
24
|
+
/**
|
|
25
|
+
* Closed polygon path for a confidence band: forward along the upper pixel
|
|
26
|
+
* edge, back along the lower. `upper` and `lower` are parallel same-length
|
|
27
|
+
* pixel-point arrays (lower typically the reverse-domain of upper's x).
|
|
28
|
+
*/
|
|
29
|
+
export declare function confidenceBandPath(upper: readonly XYPoint[], lower: readonly XYPoint[]): string | null;
|
|
30
|
+
//# sourceMappingURL=forecast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forecast.d.ts","sourceRoot":"","sources":["../../src/geometry/forecast.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAU7C,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,MAAM,WAAW,aAAa;IAC5B,oDAAoD;IACpD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8CAA8C;IAC9C,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,8CAA8C;IAC9C,EAAE,EAAE,MAAM,EAAE,CAAC;CACd;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,OAAO,EAAE,MAAM,EACf,UAAU,SAAM,GACf,aAAa,CAoCf;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,GAAG,IAAI,CAYtG"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/** Two-sided normal z-multipliers for the confidence levels the UI exposes. */
|
|
2
|
+
const Z_BY_CONFIDENCE = {
|
|
3
|
+
'0.8': 1.281_552,
|
|
4
|
+
'0.9': 1.644_854,
|
|
5
|
+
'0.95': 1.959_964,
|
|
6
|
+
'0.99': 2.575_829,
|
|
7
|
+
};
|
|
8
|
+
export function zForConfidence(confidence) {
|
|
9
|
+
return Z_BY_CONFIDENCE[String(confidence)] ?? Z_BY_CONFIDENCE['0.9'];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Ordinary-least-squares trend over the history indices, projected `horizon`
|
|
13
|
+
* steps forward. The band widens with the square root of the step distance
|
|
14
|
+
* (classic prediction-interval growth), scaled by the in-sample residual
|
|
15
|
+
* standard deviation and the confidence z-multiplier.
|
|
16
|
+
*/
|
|
17
|
+
export function linearForecast(history, horizon, confidence = 0.9) {
|
|
18
|
+
const n = history.length;
|
|
19
|
+
if (n === 0 || horizon <= 0)
|
|
20
|
+
return { forecast: [], lo: [], hi: [] };
|
|
21
|
+
const meanX = (n - 1) / 2;
|
|
22
|
+
const meanY = history.reduce((sum, v) => sum + v, 0) / n;
|
|
23
|
+
let sxx = 0;
|
|
24
|
+
let sxy = 0;
|
|
25
|
+
for (let i = 0; i < n; i += 1) {
|
|
26
|
+
const dx = i - meanX;
|
|
27
|
+
sxx += dx * dx;
|
|
28
|
+
sxy += dx * ((history[i] ?? 0) - meanY);
|
|
29
|
+
}
|
|
30
|
+
const slope = sxx === 0 ? 0 : sxy / sxx;
|
|
31
|
+
const intercept = meanY - slope * meanX;
|
|
32
|
+
let sse = 0;
|
|
33
|
+
for (let i = 0; i < n; i += 1) {
|
|
34
|
+
const fitted = intercept + slope * i;
|
|
35
|
+
const residual = (history[i] ?? 0) - fitted;
|
|
36
|
+
sse += residual * residual;
|
|
37
|
+
}
|
|
38
|
+
const residualStd = Math.sqrt(sse / Math.max(1, n - 2));
|
|
39
|
+
const z = zForConfidence(confidence);
|
|
40
|
+
const forecast = [];
|
|
41
|
+
const lo = [];
|
|
42
|
+
const hi = [];
|
|
43
|
+
for (let step = 1; step <= horizon; step += 1) {
|
|
44
|
+
const value = intercept + slope * (n - 1 + step);
|
|
45
|
+
const spread = z * residualStd * Math.sqrt(step);
|
|
46
|
+
forecast.push(value);
|
|
47
|
+
lo.push(value - spread);
|
|
48
|
+
hi.push(value + spread);
|
|
49
|
+
}
|
|
50
|
+
return { forecast, lo, hi };
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Closed polygon path for a confidence band: forward along the upper pixel
|
|
54
|
+
* edge, back along the lower. `upper` and `lower` are parallel same-length
|
|
55
|
+
* pixel-point arrays (lower typically the reverse-domain of upper's x).
|
|
56
|
+
*/
|
|
57
|
+
export function confidenceBandPath(upper, lower) {
|
|
58
|
+
if (upper.length === 0 || lower.length !== upper.length)
|
|
59
|
+
return null;
|
|
60
|
+
const parts = [];
|
|
61
|
+
upper.forEach((p, i) => {
|
|
62
|
+
parts.push(`${i === 0 ? 'M' : 'L'}${fmt(p.x)},${fmt(p.y)}`);
|
|
63
|
+
});
|
|
64
|
+
for (let i = lower.length - 1; i >= 0; i -= 1) {
|
|
65
|
+
const p = lower[i];
|
|
66
|
+
parts.push(`L${fmt(p.x)},${fmt(p.y)}`);
|
|
67
|
+
}
|
|
68
|
+
parts.push('Z');
|
|
69
|
+
return parts.join('');
|
|
70
|
+
}
|
|
71
|
+
/** Trim float noise so Node and browser emit byte-identical path strings. */
|
|
72
|
+
function fmt(value) {
|
|
73
|
+
return Number(value.toFixed(3)).toString();
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=forecast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forecast.js","sourceRoot":"","sources":["../../src/geometry/forecast.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure funnel geometry (`chart-funnel`, research/widget-registry.md §2):
|
|
3
|
+
* ordered shrinking stages with two layouts —
|
|
4
|
+
* - `horizontal`: left-aligned bars, width = value / firstValue;
|
|
5
|
+
* - `stepped`: centered bars with "N% continue" step-conversion rows.
|
|
6
|
+
* Percentages are of the first stage (overall) and of the previous stage
|
|
7
|
+
* (per-step). DOM-free + deterministic (04 §7.1).
|
|
8
|
+
*/
|
|
9
|
+
export interface FunnelStageInput {
|
|
10
|
+
label: string;
|
|
11
|
+
value: number;
|
|
12
|
+
}
|
|
13
|
+
export interface FunnelStage {
|
|
14
|
+
label: string;
|
|
15
|
+
value: number;
|
|
16
|
+
/** Width fraction relative to the FIRST stage (0..1). */
|
|
17
|
+
widthFrac: number;
|
|
18
|
+
/** Percent of the first stage, 0..100. */
|
|
19
|
+
overallPct: number;
|
|
20
|
+
/** Percent retained vs the PREVIOUS stage, 0..100 (first stage = 100). */
|
|
21
|
+
stepPct: number;
|
|
22
|
+
/** Inline-start offset fraction for centered (stepped) layout (0..0.5). */
|
|
23
|
+
offsetFrac: number;
|
|
24
|
+
colorVar: string;
|
|
25
|
+
}
|
|
26
|
+
export interface FunnelLayout {
|
|
27
|
+
stages: FunnelStage[];
|
|
28
|
+
/** Overall conversion first→last, 0..100. */
|
|
29
|
+
overallConversion: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Funnel stages in input order. Non-finite values clamp to 0; the first
|
|
33
|
+
* positive value is the 100% reference. Returns [] when there is no positive
|
|
34
|
+
* head stage.
|
|
35
|
+
*/
|
|
36
|
+
export declare function funnelLayout(input: readonly FunnelStageInput[]): FunnelLayout;
|
|
37
|
+
//# sourceMappingURL=funnel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"funnel.d.ts","sourceRoot":"","sources":["../../src/geometry/funnel.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,6CAA6C;IAC7C,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AASD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,GAAG,YAAY,CAqB7E"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure funnel geometry (`chart-funnel`, research/widget-registry.md §2):
|
|
3
|
+
* ordered shrinking stages with two layouts —
|
|
4
|
+
* - `horizontal`: left-aligned bars, width = value / firstValue;
|
|
5
|
+
* - `stepped`: centered bars with "N% continue" step-conversion rows.
|
|
6
|
+
* Percentages are of the first stage (overall) and of the previous stage
|
|
7
|
+
* (per-step). DOM-free + deterministic (04 §7.1).
|
|
8
|
+
*/
|
|
9
|
+
function vizAlphaVar(index, count) {
|
|
10
|
+
// Fade the accent alpha ramp down the funnel (annex "fading accent alpha").
|
|
11
|
+
if (count <= 1)
|
|
12
|
+
return 'var(--viz-ramp-6)';
|
|
13
|
+
const step = 6 - Math.round((index / (count - 1)) * 4); // 6 → 2 across stages
|
|
14
|
+
return `var(--viz-ramp-${Math.min(6, Math.max(2, step))})`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Funnel stages in input order. Non-finite values clamp to 0; the first
|
|
18
|
+
* positive value is the 100% reference. Returns [] when there is no positive
|
|
19
|
+
* head stage.
|
|
20
|
+
*/
|
|
21
|
+
export function funnelLayout(input) {
|
|
22
|
+
const stages = input.map((s) => ({ label: s.label, value: Number.isFinite(s.value) ? Math.max(0, s.value) : 0 }));
|
|
23
|
+
const head = stages[0]?.value ?? 0;
|
|
24
|
+
if (stages.length === 0 || head <= 0)
|
|
25
|
+
return { stages: [], overallConversion: 0 };
|
|
26
|
+
const out = stages.map((stage, i) => {
|
|
27
|
+
const prev = stages[i - 1]?.value ?? head;
|
|
28
|
+
const widthFrac = stage.value / head;
|
|
29
|
+
return {
|
|
30
|
+
label: stage.label,
|
|
31
|
+
value: stage.value,
|
|
32
|
+
widthFrac,
|
|
33
|
+
overallPct: widthFrac * 100,
|
|
34
|
+
stepPct: prev > 0 ? (stage.value / prev) * 100 : 0,
|
|
35
|
+
offsetFrac: (1 - widthFrac) / 2,
|
|
36
|
+
colorVar: vizAlphaVar(i, stages.length),
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
const tail = stages.at(-1)?.value ?? 0;
|
|
40
|
+
return { stages: out, overallConversion: (tail / head) * 100 };
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=funnel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"funnel.js","sourceRoot":"","sources":["../../src/geometry/funnel.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA2BH,SAAS,WAAW,CAAC,KAAa,EAAE,KAAa;IAC/C,4EAA4E;IAC5E,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,mBAAmB,CAAC;IAC3C,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,sBAAsB;IAC9E,OAAO,kBAAkB,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC;AAC7D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,KAAkC;IAC7D,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClH,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC;IACnC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC;IAElF,MAAM,GAAG,GAAkB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QACjD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC;QAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;QACrC,OAAO;YACL,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,SAAS;YACT,UAAU,EAAE,SAAS,GAAG,GAAG;YAC3B,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YAClD,UAAU,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC;YAC/B,QAAQ,EAAE,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC;SACxC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC;IACvC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared heat-intensity helpers for the matrix/calendar/geo charts (Track E).
|
|
3
|
+
* Pure and DOM-free (workplan/04-widget-registry.md §7.1) so scheduled-report
|
|
4
|
+
* workers reuse them. Sequential intensity maps onto the accent alpha ramp
|
|
5
|
+
* `--viz-ramp-1..6` (research/design-system.md §1.3 / tokens viz.css); zero maps
|
|
6
|
+
* to the neutral `--surface-2` empty cell. No hex literals — colors are var()
|
|
7
|
+
* expressions only (acceptance #8).
|
|
8
|
+
*/
|
|
9
|
+
/** Number of steps in the accent alpha ramp exposed by @adminium/tokens. */
|
|
10
|
+
export declare const RAMP_STEPS = 6;
|
|
11
|
+
/**
|
|
12
|
+
* Ramp index (1..RAMP_STEPS) for a heat `level` within a scale of `levels`
|
|
13
|
+
* total levels (level 0 excluded — it is the empty cell). Level `levels-1`
|
|
14
|
+
* always lands on the darkest ramp step.
|
|
15
|
+
*/
|
|
16
|
+
export declare function rampIndex(level: number, levels: number): number;
|
|
17
|
+
/**
|
|
18
|
+
* CSS color for a heat `level`: level 0 → neutral empty cell (`--surface-2`);
|
|
19
|
+
* levels 1..levels-1 → `--viz-ramp-N` accent-alpha steps.
|
|
20
|
+
*/
|
|
21
|
+
export declare function rampColorVar(level: number, levels: number): string;
|
|
22
|
+
/**
|
|
23
|
+
* Discrete heat level 0..levels-1 for a `value` over `[0, maxValue]`. Zero (or
|
|
24
|
+
* non-positive) values are level 0 (empty); positive values span 1..levels-1
|
|
25
|
+
* linearly, with `maxValue` landing on the top level. `levels` must be ≥ 2.
|
|
26
|
+
*/
|
|
27
|
+
export declare function heatLevel(value: number, maxValue: number, levels: number): number;
|
|
28
|
+
/**
|
|
29
|
+
* Whether tile label text should flip to the on-accent color (`--accent-fg`):
|
|
30
|
+
* true once the ramp step is dark enough (≥ 65% alpha, ramp index ≥ 4) to lose
|
|
31
|
+
* contrast against the default foreground.
|
|
32
|
+
*/
|
|
33
|
+
export declare function heatTextLight(level: number, levels: number): boolean;
|
|
34
|
+
//# sourceMappingURL=heat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heat.d.ts","sourceRoot":"","sources":["../../src/geometry/heat.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,4EAA4E;AAC5E,eAAO,MAAM,UAAU,IAAI,CAAC;AAE5B;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAI/D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGlE;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAKjF;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAEpE"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared heat-intensity helpers for the matrix/calendar/geo charts (Track E).
|
|
3
|
+
* Pure and DOM-free (workplan/04-widget-registry.md §7.1) so scheduled-report
|
|
4
|
+
* workers reuse them. Sequential intensity maps onto the accent alpha ramp
|
|
5
|
+
* `--viz-ramp-1..6` (research/design-system.md §1.3 / tokens viz.css); zero maps
|
|
6
|
+
* to the neutral `--surface-2` empty cell. No hex literals — colors are var()
|
|
7
|
+
* expressions only (acceptance #8).
|
|
8
|
+
*/
|
|
9
|
+
/** Number of steps in the accent alpha ramp exposed by @adminium/tokens. */
|
|
10
|
+
export const RAMP_STEPS = 6;
|
|
11
|
+
/**
|
|
12
|
+
* Ramp index (1..RAMP_STEPS) for a heat `level` within a scale of `levels`
|
|
13
|
+
* total levels (level 0 excluded — it is the empty cell). Level `levels-1`
|
|
14
|
+
* always lands on the darkest ramp step.
|
|
15
|
+
*/
|
|
16
|
+
export function rampIndex(level, levels) {
|
|
17
|
+
if (level <= 0)
|
|
18
|
+
return 0;
|
|
19
|
+
const span = Math.max(1, levels - 1);
|
|
20
|
+
return Math.min(RAMP_STEPS, Math.max(1, Math.round((level / span) * RAMP_STEPS)));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* CSS color for a heat `level`: level 0 → neutral empty cell (`--surface-2`);
|
|
24
|
+
* levels 1..levels-1 → `--viz-ramp-N` accent-alpha steps.
|
|
25
|
+
*/
|
|
26
|
+
export function rampColorVar(level, levels) {
|
|
27
|
+
const index = rampIndex(level, levels);
|
|
28
|
+
return index === 0 ? 'var(--surface-2)' : `var(--viz-ramp-${index})`;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Discrete heat level 0..levels-1 for a `value` over `[0, maxValue]`. Zero (or
|
|
32
|
+
* non-positive) values are level 0 (empty); positive values span 1..levels-1
|
|
33
|
+
* linearly, with `maxValue` landing on the top level. `levels` must be ≥ 2.
|
|
34
|
+
*/
|
|
35
|
+
export function heatLevel(value, maxValue, levels) {
|
|
36
|
+
if (value <= 0 || maxValue <= 0 || levels < 2)
|
|
37
|
+
return 0;
|
|
38
|
+
const frac = Math.min(1, value / maxValue);
|
|
39
|
+
const bucket = Math.min(levels - 2, Math.floor(frac * (levels - 1)));
|
|
40
|
+
return 1 + bucket;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Whether tile label text should flip to the on-accent color (`--accent-fg`):
|
|
44
|
+
* true once the ramp step is dark enough (≥ 65% alpha, ramp index ≥ 4) to lose
|
|
45
|
+
* contrast against the default foreground.
|
|
46
|
+
*/
|
|
47
|
+
export function heatTextLight(level, levels) {
|
|
48
|
+
return rampIndex(level, levels) >= 4;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=heat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heat.js","sourceRoot":"","sources":["../../src/geometry/heat.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,4EAA4E;AAC5E,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAE5B;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,MAAc;IACrD,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACzB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;AACpF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,MAAc;IACxD,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACvC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,kBAAkB,KAAK,GAAG,CAAC;AACvE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,QAAgB,EAAE,MAAc;IACvE,IAAI,KAAK,IAAI,CAAC,IAAI,QAAQ,IAAI,CAAC,IAAI,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,OAAO,CAAC,GAAG,MAAM,CAAC;AACpB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,MAAc;IACzD,OAAO,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface HeatDay {
|
|
2
|
+
weekIndex: number;
|
|
3
|
+
dayIndex: number;
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
size: number;
|
|
7
|
+
/** UTC midnight of the day. */
|
|
8
|
+
date: Date;
|
|
9
|
+
/** ISO date key (YYYY-MM-DD). */
|
|
10
|
+
key: string;
|
|
11
|
+
value: number;
|
|
12
|
+
level: number;
|
|
13
|
+
}
|
|
14
|
+
export interface HeatCalendarLayout {
|
|
15
|
+
days: HeatDay[];
|
|
16
|
+
weeks: number;
|
|
17
|
+
/** Day-of-week row order actually used (0=Sun..6=Sat), rotated by startWeekday. */
|
|
18
|
+
weekdayRows: number[];
|
|
19
|
+
maxValue: number;
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
}
|
|
23
|
+
export interface HeatCalendarOptions {
|
|
24
|
+
/** Number of week columns (default 53). */
|
|
25
|
+
weeks?: number;
|
|
26
|
+
/** First weekday of the column, 0=Sun..6=Sat (locale-aware). Default 0. */
|
|
27
|
+
startWeekday?: number;
|
|
28
|
+
cellSize?: number;
|
|
29
|
+
gap?: number;
|
|
30
|
+
/** Intensity levels incl. 0 (default 5). */
|
|
31
|
+
levels?: number;
|
|
32
|
+
rtl?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface HeatPoint {
|
|
35
|
+
t: string | number | Date;
|
|
36
|
+
v: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Lay out daily counts into a week×day grid ending at the latest point's week.
|
|
40
|
+
* Days after the latest point (future cells in the final week) are omitted.
|
|
41
|
+
*/
|
|
42
|
+
export declare function heatCalendarLayout(points: readonly HeatPoint[], options?: HeatCalendarOptions): HeatCalendarLayout;
|
|
43
|
+
//# sourceMappingURL=heatCalendar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heatCalendar.d.ts","sourceRoot":"","sources":["../../src/geometry/heatCalendar.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,IAAI,EAAE,IAAI,CAAC;IACX,iCAAiC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,mFAAmF;IACnF,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAcD,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC1B,CAAC,EAAE,MAAM,CAAC;CACX;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,SAAS,SAAS,EAAE,EAC5B,OAAO,GAAE,mBAAwB,GAChC,kBAAkB,CAuDpB"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure GitHub-style contribution-calendar geometry (research/widget-registry.md
|
|
3
|
+
* §2 `chart-heatmap-calendar`): up to 53 week columns × 7 day rows of per-day
|
|
4
|
+
* counts, discrete intensity levels, a less→more legend. DOM-free and
|
|
5
|
+
* deterministic (workplan/04 §7.1) — UTC-only date math, no `Date.now()`.
|
|
6
|
+
*
|
|
7
|
+
* RTL policy (04 §7.4, explicit): the week columns run right→left under `rtl`
|
|
8
|
+
* (newest week on the inline-start edge); the day rows never move.
|
|
9
|
+
*/
|
|
10
|
+
import { heatLevel } from './heat.js';
|
|
11
|
+
const DAY_MS = 86_400_000;
|
|
12
|
+
/** UTC midnight for an ISO/date input; invalid → null. */
|
|
13
|
+
function utcMidnight(input) {
|
|
14
|
+
const d = input instanceof Date ? input : new Date(input);
|
|
15
|
+
const ms = d.getTime();
|
|
16
|
+
if (Number.isNaN(ms))
|
|
17
|
+
return null;
|
|
18
|
+
return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));
|
|
19
|
+
}
|
|
20
|
+
function isoKey(date) {
|
|
21
|
+
return date.toISOString().slice(0, 10);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Lay out daily counts into a week×day grid ending at the latest point's week.
|
|
25
|
+
* Days after the latest point (future cells in the final week) are omitted.
|
|
26
|
+
*/
|
|
27
|
+
export function heatCalendarLayout(points, options = {}) {
|
|
28
|
+
const { weeks = 53, startWeekday = 0, cellSize = 12, gap = 3, levels = 5, rtl = false } = options;
|
|
29
|
+
const step = cellSize + gap;
|
|
30
|
+
const counts = new Map();
|
|
31
|
+
let end = null;
|
|
32
|
+
let maxValue = 0;
|
|
33
|
+
for (const point of points) {
|
|
34
|
+
const date = utcMidnight(point.t);
|
|
35
|
+
if (date === null)
|
|
36
|
+
continue;
|
|
37
|
+
const key = isoKey(date);
|
|
38
|
+
const v = Number.isFinite(point.v) ? point.v : 0;
|
|
39
|
+
counts.set(key, v);
|
|
40
|
+
if (v > maxValue)
|
|
41
|
+
maxValue = v;
|
|
42
|
+
if (end === null || date.getTime() > end.getTime())
|
|
43
|
+
end = date;
|
|
44
|
+
}
|
|
45
|
+
const endDate = end ?? new Date(Date.UTC(1970, 0, 1));
|
|
46
|
+
// Row index of a date within a column that starts on `startWeekday`.
|
|
47
|
+
const rowOf = (date) => (date.getUTCDay() - startWeekday + 7) % 7;
|
|
48
|
+
const endRow = rowOf(endDate);
|
|
49
|
+
const days = [];
|
|
50
|
+
for (let col = 0; col < weeks; col += 1) {
|
|
51
|
+
for (let row = 0; row < 7; row += 1) {
|
|
52
|
+
// Days back from the end date: whole weeks + within-week row delta.
|
|
53
|
+
const daysFromEnd = (weeks - 1 - col) * 7 + (endRow - row);
|
|
54
|
+
if (daysFromEnd < 0)
|
|
55
|
+
continue; // future cell in the final week
|
|
56
|
+
const date = new Date(endDate.getTime() - daysFromEnd * DAY_MS);
|
|
57
|
+
const key = isoKey(date);
|
|
58
|
+
const value = counts.get(key) ?? 0;
|
|
59
|
+
days.push({
|
|
60
|
+
weekIndex: col,
|
|
61
|
+
dayIndex: row,
|
|
62
|
+
x: (rtl ? weeks - 1 - col : col) * step,
|
|
63
|
+
y: row * step,
|
|
64
|
+
size: cellSize,
|
|
65
|
+
date,
|
|
66
|
+
key,
|
|
67
|
+
value,
|
|
68
|
+
level: heatLevel(value, maxValue, levels),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const weekdayRows = Array.from({ length: 7 }, (_, i) => (startWeekday + i) % 7);
|
|
73
|
+
return {
|
|
74
|
+
days,
|
|
75
|
+
weeks,
|
|
76
|
+
weekdayRows,
|
|
77
|
+
maxValue,
|
|
78
|
+
width: weeks > 0 ? weeks * step - gap : 0,
|
|
79
|
+
height: 7 * step - gap,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=heatCalendar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heatCalendar.js","sourceRoot":"","sources":["../../src/geometry/heatCalendar.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface HeatMonthCell {
|
|
2
|
+
row: number;
|
|
3
|
+
col: number;
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
size: number;
|
|
7
|
+
/** Day of month (1..31) or null for padding cells outside the month. */
|
|
8
|
+
day: number | null;
|
|
9
|
+
/** ISO date key for in-month cells. */
|
|
10
|
+
key: string | null;
|
|
11
|
+
value: number;
|
|
12
|
+
level: number;
|
|
13
|
+
}
|
|
14
|
+
export interface HeatMonthLayout {
|
|
15
|
+
cells: HeatMonthCell[];
|
|
16
|
+
/** Header column order (0=Sun..6=Sat) rotated by startWeekday, in draw order. */
|
|
17
|
+
headerCols: {
|
|
18
|
+
col: number;
|
|
19
|
+
weekday: number;
|
|
20
|
+
x: number;
|
|
21
|
+
}[];
|
|
22
|
+
rows: number;
|
|
23
|
+
maxValue: number;
|
|
24
|
+
headerHeight: number;
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
}
|
|
28
|
+
export interface HeatMonthOptions {
|
|
29
|
+
/** First weekday of the row, 0=Sun..6=Sat (locale-aware). Default 0. */
|
|
30
|
+
startWeekday?: number;
|
|
31
|
+
cellSize?: number;
|
|
32
|
+
gap?: number;
|
|
33
|
+
headerHeight?: number;
|
|
34
|
+
/** Intensity levels incl. 0 (default 5). */
|
|
35
|
+
levels?: number;
|
|
36
|
+
rtl?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface HeatMonthPoint {
|
|
39
|
+
t: string | number | Date;
|
|
40
|
+
v: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Lay out one calendar month (0-based `month`) of daily counts. Padding cells
|
|
44
|
+
* before the 1st and after the last day carry `day: null`.
|
|
45
|
+
*/
|
|
46
|
+
export declare function heatMonthLayout(year: number, month: number, points: readonly HeatMonthPoint[], options?: HeatMonthOptions): HeatMonthLayout;
|
|
47
|
+
//# sourceMappingURL=heatMonth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heatMonth.d.ts","sourceRoot":"","sources":["../../src/geometry/heatMonth.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,uCAAuC;IACvC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,iFAAiF;IACjF,UAAU,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC1B,CAAC,EAAE,MAAM,CAAC;CACX;AAMD;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,OAAO,GAAE,gBAAqB,GAC7B,eAAe,CAgEjB"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure single-month heat-grid geometry (research/widget-registry.md §2
|
|
3
|
+
* `chart-heat-month`): a 7-column month calendar with day numbers and up to 5
|
|
4
|
+
* intensity levels + a day-of-week header. DOM-free and deterministic
|
|
5
|
+
* (workplan/04 §7.1) — UTC-only date math.
|
|
6
|
+
*
|
|
7
|
+
* RTL policy (04 §7.4): the day-of-week columns are a horizontal categorical
|
|
8
|
+
* scale and mirror under `rtl`; the week rows never move.
|
|
9
|
+
*/
|
|
10
|
+
import { heatLevel } from './heat.js';
|
|
11
|
+
function pad2(n) {
|
|
12
|
+
return n < 10 ? `0${n}` : String(n);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Lay out one calendar month (0-based `month`) of daily counts. Padding cells
|
|
16
|
+
* before the 1st and after the last day carry `day: null`.
|
|
17
|
+
*/
|
|
18
|
+
export function heatMonthLayout(year, month, points, options = {}) {
|
|
19
|
+
const { startWeekday = 0, cellSize = 40, gap = 4, headerHeight = 20, levels = 5, rtl = false, } = options;
|
|
20
|
+
const step = cellSize + gap;
|
|
21
|
+
const counts = new Map();
|
|
22
|
+
let maxValue = 0;
|
|
23
|
+
for (const point of points) {
|
|
24
|
+
const d = point.t instanceof Date ? point.t : new Date(point.t);
|
|
25
|
+
if (Number.isNaN(d.getTime()))
|
|
26
|
+
continue;
|
|
27
|
+
const key = `${d.getUTCFullYear()}-${pad2(d.getUTCMonth() + 1)}-${pad2(d.getUTCDate())}`;
|
|
28
|
+
const v = Number.isFinite(point.v) ? point.v : 0;
|
|
29
|
+
counts.set(key, v);
|
|
30
|
+
if (v > maxValue)
|
|
31
|
+
maxValue = v;
|
|
32
|
+
}
|
|
33
|
+
const firstDow = (new Date(Date.UTC(year, month, 1)).getUTCDay() - startWeekday + 7) % 7;
|
|
34
|
+
const daysInMonth = new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
|
|
35
|
+
const rows = Math.ceil((firstDow + daysInMonth) / 7);
|
|
36
|
+
const colX = (col) => (rtl ? 6 - col : col) * step;
|
|
37
|
+
const cells = [];
|
|
38
|
+
for (let row = 0; row < rows; row += 1) {
|
|
39
|
+
for (let col = 0; col < 7; col += 1) {
|
|
40
|
+
const day = row * 7 + col - firstDow + 1;
|
|
41
|
+
const inMonth = day >= 1 && day <= daysInMonth;
|
|
42
|
+
const key = inMonth ? `${year}-${pad2(month + 1)}-${pad2(day)}` : null;
|
|
43
|
+
const value = key !== null ? (counts.get(key) ?? 0) : 0;
|
|
44
|
+
cells.push({
|
|
45
|
+
row,
|
|
46
|
+
col,
|
|
47
|
+
x: colX(col),
|
|
48
|
+
y: headerHeight + row * step,
|
|
49
|
+
size: cellSize,
|
|
50
|
+
day: inMonth ? day : null,
|
|
51
|
+
key,
|
|
52
|
+
value,
|
|
53
|
+
level: inMonth ? heatLevel(value, maxValue, levels) : 0,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const headerCols = Array.from({ length: 7 }, (_, col) => ({
|
|
58
|
+
col,
|
|
59
|
+
weekday: (startWeekday + col) % 7,
|
|
60
|
+
x: colX(col) + cellSize / 2,
|
|
61
|
+
}));
|
|
62
|
+
return {
|
|
63
|
+
cells,
|
|
64
|
+
headerCols,
|
|
65
|
+
rows,
|
|
66
|
+
maxValue,
|
|
67
|
+
headerHeight,
|
|
68
|
+
width: 7 * step - gap,
|
|
69
|
+
height: headerHeight + rows * step - gap,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=heatMonth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heatMonth.js","sourceRoot":"","sources":["../../src/geometry/heatMonth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface XYPoint {
|
|
2
|
+
/** Pixel-space x. */
|
|
3
|
+
x: number;
|
|
4
|
+
/** Pixel-space y. */
|
|
5
|
+
y: number;
|
|
6
|
+
}
|
|
7
|
+
/** SVG path for a polyline through pixel-space points. Null when < 1 point. */
|
|
8
|
+
export declare function linePath(points: readonly XYPoint[], smooth?: boolean): string | null;
|
|
9
|
+
/** SVG path for the area under the line, closed at `baselineY`. */
|
|
10
|
+
export declare function areaPath(points: readonly XYPoint[], baselineY: number, smooth?: boolean): string | null;
|
|
11
|
+
/**
|
|
12
|
+
* Index of the point whose pixel x is nearest to `targetX`. Works for both
|
|
13
|
+
* ascending (LTR) and descending (RTL categorical) x sequences — linear scan,
|
|
14
|
+
* chart series are small. Returns -1 for empty input.
|
|
15
|
+
*/
|
|
16
|
+
export declare function nearestIndexByX(xs: readonly number[], targetX: number): number;
|
|
17
|
+
//# sourceMappingURL=lineArea.d.ts.map
|