website: redesign part 27

This commit is contained in:
nym21
2026-06-09 13:35:21 +02:00
parent c3506339cd
commit 5966ab05e4
29 changed files with 174 additions and 290 deletions
+5 -12
View File
@@ -5,7 +5,8 @@ import { createLineSeries } from "../line/series.js";
/**
* @param {number} height
* @param {{ date: Date, value: number, x: number, y: number }[]} points
* @param {ChartPoint[]} points
* @returns {StackedPoint[]}
*/
function createAreaPoints(height, points) {
return points.map((point) => ({
@@ -16,21 +17,16 @@ function createAreaPoints(height, points) {
}
/**
* @param {SVGGElement} group
* @param {LoadedSeries[]} loadedSeries
* @param {number} height
* @param {SeriesHighlight} highlight
* @param {import("../scale.js").ChartScale} scale
* @param {import("../order.js").ChartOrder} order
* @param {PlotContext} context
*/
export function renderAreaPlot(
export function renderAreaPlot({
group,
loadedSeries,
height,
highlight,
scale,
order,
) {
}) {
const plottedSeries = createLineSeries(loadedSeries, height, scale);
const indexes = createOrderedIndexes(plottedSeries.length, order);
@@ -57,6 +53,3 @@ export function renderAreaPlot(
return plottedSeries;
}
/** @typedef {import("../highlight.js").SeriesHighlight} SeriesHighlight */
/** @typedef {import("../index.js").LoadedSeries} LoadedSeries */
+5 -13
View File
@@ -4,13 +4,13 @@ import { createStackedSeries } from "../stacked/series.js";
import { clamp } from "../math.js";
import { appendSeriesPath } from "../series-path.js";
/** @param {{ x: number, y0: number, y1: number }[]} points */
/** @param {StackedPoint[]} points */
function getBarWidth(points) {
return points.length > 1 ? (VIEWBOX_WIDTH / (points.length - 1)) * 0.8 : 1;
}
/**
* @param {{ x: number, y0: number, y1: number }[]} points
* @param {StackedPoint[]} points
* @param {number} width
*/
function createBarPathData(points, width) {
@@ -31,21 +31,16 @@ function createBarPathData(points, width) {
}
/**
* @param {SVGGElement} group
* @param {LoadedSeries[]} loadedSeries
* @param {number} height
* @param {SeriesHighlight} highlight
* @param {import("../scale.js").ChartScale} scale
* @param {import("../order.js").ChartOrder} order
* @param {PlotContext} context
*/
export function renderBarPlot(
export function renderBarPlot({
group,
loadedSeries,
height,
highlight,
scale,
order,
) {
}) {
const { lineIndexes, plottedSeries, stackIndexes } = createStackedSeries(
loadedSeries,
height,
@@ -79,6 +74,3 @@ export function renderBarPlot(
return plottedSeries;
}
/** @typedef {import("../highlight.js").SeriesHighlight} SeriesHighlight */
/** @typedef {import("../index.js").LoadedSeries} LoadedSeries */
+4 -12
View File
@@ -5,7 +5,7 @@ import { createLineSeries } from "../line/series.js";
const radius = 1;
/** @param {{ x: number, y: number }[]} points */
/** @param {ChartPoint[]} points */
function createDotsPathData(points) {
return points
.map(
@@ -18,21 +18,16 @@ function createDotsPathData(points) {
}
/**
* @param {SVGGElement} group
* @param {LoadedSeries[]} loadedSeries
* @param {number} height
* @param {SeriesHighlight} highlight
* @param {import("../scale.js").ChartScale} scale
* @param {import("../order.js").ChartOrder} order
* @param {PlotContext} context
*/
export function renderDotsPlot(
export function renderDotsPlot({
group,
loadedSeries,
height,
highlight,
scale,
order,
) {
}) {
const plottedSeries = createLineSeries(loadedSeries, height, scale);
const indexes = createOrderedIndexes(plottedSeries.length, order);
@@ -50,6 +45,3 @@ export function renderDotsPlot(
return plottedSeries;
}
/** @typedef {import("../highlight.js").SeriesHighlight} SeriesHighlight */
/** @typedef {import("../index.js").LoadedSeries} LoadedSeries */
-8
View File
@@ -150,11 +150,3 @@ function clearElementState(element) {
}
/** @typedef {(SVGPathElement | SVGCircleElement)[]} SeriesNode */
/**
* @typedef {Object} SeriesHighlight
* @property {(node: SVGPathElement | SVGCircleElement, index: number) => void} addNode
* @property {() => void} clearPreview
* @property {() => void} clearNodes
* @property {(index: number) => void} preview
*/
-29
View File
@@ -131,32 +131,3 @@ export function createChart(chart, chartKey) {
return figure;
}
/**
* @typedef {Object} Chart
* @property {string} title
* @property {import("./units.js").ChartUnit} unit
* @property {import("./views.js").ChartView} [defaultType]
* @property {import("./scale.js").ChartScale} [defaultScale]
* @property {ChartSeries[]} series
*/
/**
* @typedef {Object} ChartSeries
* @property {string} label
* @property {() => string} color
* @property {"line"} [role]
* @property {(client: typeof import("../../utils/client.js").brk) => import("./timeframes.js").TimeframeMetric} metric
*/
/**
* @typedef {Object} ChartResult
* @property {() => Iterable<[Date, number | null | undefined]>} dateEntries
*/
/**
* @typedef {Object} LoadedSeries
* @property {ChartSeries} series
* @property {string} color
* @property {{ date: Date, value: number }[]} entries
*/
+1 -9
View File
@@ -1,6 +1,6 @@
/**
* @param {Chart} chart
* @returns {{ legend: HTMLElement, menu: HTMLElement, items: HTMLElement[], readout: Readout }}
* @returns {{ legend: HTMLElement, menu: HTMLElement, items: HTMLElement[], readout: LegendReadout }}
*/
export function createLegend(chart) {
const legend = document.createElement("figcaption");
@@ -41,11 +41,3 @@ export function createLegend(chart) {
return { legend, menu, items, readout: { time, rows } };
}
/**
* @typedef {Object} Readout
* @property {HTMLTimeElement} time
* @property {{ value: HTMLOutputElement }[]} rows
*/
/** @typedef {import("../index.js").Chart} Chart */
+4 -12
View File
@@ -1,24 +1,19 @@
import { createOrderedIndexes } from "../order.js";
import { createLinePathData } from "../path.js";
import { appendSeriesPath } from "../series-path.js";
import { createOrderedIndexes } from "../order.js";
import { createLineSeries } from "./series.js";
/**
* @param {SVGGElement} group
* @param {LoadedSeries[]} loadedSeries
* @param {number} height
* @param {SeriesHighlight} highlight
* @param {import("../scale.js").ChartScale} scale
* @param {import("../order.js").ChartOrder} order
* @param {PlotContext} context
*/
export function renderLinePlot(
export function renderLinePlot({
group,
loadedSeries,
height,
highlight,
scale,
order,
) {
}) {
const plottedSeries = createLineSeries(loadedSeries, height, scale);
const indexes = createOrderedIndexes(plottedSeries.length, order);
@@ -36,6 +31,3 @@ export function renderLinePlot(
return plottedSeries;
}
/** @typedef {import("../highlight.js").SeriesHighlight} SeriesHighlight */
/** @typedef {import("../index.js").LoadedSeries} LoadedSeries */
+5 -6
View File
@@ -15,10 +15,11 @@ function createValueBounds(series) {
}
/**
* @param {{ date: Date, value: number }[]} entries
* @param {import("../scale.js").ScaleBounds} bounds
* @param {ChartEntry[]} entries
* @param {ScaleBounds} bounds
* @param {number} height
* @param {import("../scale.js").ChartScale} scale
* @param {ChartScale} scale
* @returns {ChartPoint[]}
*/
function createPoints(entries, bounds, height, scale) {
const xScale = VIEWBOX_WIDTH / (entries.length - 1);
@@ -34,7 +35,7 @@ function createPoints(entries, bounds, height, scale) {
/**
* @param {LoadedSeries[]} loadedSeries
* @param {number} height
* @param {import("../scale.js").ChartScale} scale
* @param {ChartScale} scale
*/
export function createLineSeries(loadedSeries, height, scale) {
const bounds = createValueBounds(loadedSeries);
@@ -45,5 +46,3 @@ export function createLineSeries(loadedSeries, height, scale) {
points: createPoints(entries, bounds, height, scale),
}));
}
/** @typedef {import("../index.js").LoadedSeries} LoadedSeries */
+2 -7
View File
@@ -3,10 +3,10 @@ import { fetchTimeframe } from "./timeframes.js";
/**
* @param {ChartResult} result
* @returns {{ date: Date, value: number }[]}
* @returns {ChartEntry[]}
*/
function createEntries(result) {
/** @type {{ date: Date, value: number }[]} */
/** @type {ChartEntry[]} */
const entries = [];
/** @type {number | undefined} */
let lastValue;
@@ -53,8 +53,3 @@ export function createSeriesLoader(chart) {
return cachedPromise;
};
}
/** @typedef {import("./index.js").Chart} Chart */
/** @typedef {import("./index.js").ChartResult} ChartResult */
/** @typedef {import("./index.js").LoadedSeries} LoadedSeries */
/** @typedef {import("./timeframes.js").TimeframeValue} TimeframeValue */
+1 -3
View File
@@ -1,6 +1,6 @@
import { createChartSetting } from "./setting.js";
const orders = /** @type {const} */ ([
export const orders = /** @type {const} */ ([
{ value: "ascending", label: "Asc" },
{ value: "descending", label: "Dsc" },
]);
@@ -55,5 +55,3 @@ export function createOrderedIndexes(length, order) {
order,
);
}
/** @typedef {(typeof orders)[number]["value"]} ChartOrder */
+2 -2
View File
@@ -12,14 +12,14 @@ function createPathCommand(command, x, y) {
return `${command}${formatCoordinate(x)} ${formatCoordinate(y)}`;
}
/** @param {{ x: number, y: number }[]} points */
/** @param {ChartPoint[]} points */
export function createLinePathData(points) {
return points
.map(({ x, y }, index) => createPathCommand(index ? "L" : "M", x, y))
.join(" ");
}
/** @param {{ x: number, y0: number, y1: number }[]} points */
/** @param {StackedPoint[]} points */
export function createAreaPathData(points) {
const commands = points.map(({ x, y1 }, index) =>
createPathCommand(index ? "L" : "M", x, y1),
+7 -54
View File
@@ -6,66 +6,19 @@ import { renderStackedPlot } from "./stacked/index.js";
/**
* @param {ChartView} view
* @param {SVGGElement} group
* @param {LoadedSeries[]} loadedSeries
* @param {number} height
* @param {SeriesHighlight} highlight
* @param {ChartScale} scale
* @param {ChartOrder} order
* @param {PlotContext} context
*/
export function renderPlot(
view,
group,
loadedSeries,
height,
highlight,
scale,
order,
) {
export function renderPlot(view, context) {
switch (view) {
case "line":
return renderLinePlot(
group,
loadedSeries,
height,
highlight,
scale,
order,
);
return renderLinePlot(context);
case "area":
return renderAreaPlot(
group,
loadedSeries,
height,
highlight,
scale,
order,
);
return renderAreaPlot(context);
case "bar":
return renderBarPlot(group, loadedSeries, height, highlight, scale, order);
return renderBarPlot(context);
case "dots":
return renderDotsPlot(
group,
loadedSeries,
height,
highlight,
scale,
order,
);
return renderDotsPlot(context);
case "stacked":
return renderStackedPlot(
group,
loadedSeries,
height,
highlight,
scale,
order,
);
return renderStackedPlot(context);
}
}
/** @typedef {import("./highlight.js").SeriesHighlight} SeriesHighlight */
/** @typedef {import("./index.js").LoadedSeries} LoadedSeries */
/** @typedef {import("./order.js").ChartOrder} ChartOrder */
/** @typedef {import("./scale.js").ChartScale} ChartScale */
/** @typedef {import("./views.js").ChartView} ChartView */
+5 -15
View File
@@ -8,7 +8,7 @@ import { getViewBoxHeight, VIEWBOX_WIDTH } from "./viewbox.js";
/**
* @param {Object} args
* @param {SVGSVGElement} args.svg
* @param {Readout} args.readout
* @param {LegendReadout} args.readout
* @param {HTMLElement} args.menu
* @param {HTMLElement[]} args.items
* @param {HTMLElement} args.status
@@ -63,15 +63,14 @@ export function createChartRenderer({
highlight.clearNodes();
scrubber ??= createScrubber(svg, readout, highlight, chart.unit.format);
scrubber.setSeries(
renderPlot(
getView(),
renderPlot(getView(), {
group,
loadedSeries,
height,
highlight,
getScale(),
getOrder(),
),
scale: getScale(),
order: getOrder(),
}),
height,
);
}
@@ -131,12 +130,3 @@ export function createChartRenderer({
suspend,
};
}
/** @typedef {import("./index.js").Chart} Chart */
/** @typedef {import("./index.js").LoadedSeries} LoadedSeries */
/** @typedef {import("./legend/index.js").Readout} Readout */
/** @typedef {import("./order.js").ChartOrder} ChartOrder */
/** @typedef {import("./scale.js").ChartScale} ChartScale */
/** @typedef {import("./timeframes.js").TimeframeValue} TimeframeValue */
/** @typedef {import("./views.js").ChartView} ChartView */
/** @typedef {import("./highlight.js").SeriesHighlight} SeriesHighlight */
+1 -10
View File
@@ -1,6 +1,6 @@
import { createChartSetting } from "./setting.js";
const scales = /** @type {const} */ ([
export const scales = /** @type {const} */ ([
{ value: "linear", label: "Lin" },
{ value: "log", label: "Log" },
]);
@@ -79,12 +79,3 @@ export function scaleY(value, bounds, height, scale) {
return height - ((value - bounds.min) / (bounds.max - bounds.min)) * height;
}
/**
* @typedef {Object} ScaleBounds
* @property {number} min
* @property {number} max
* @property {number} minPositive
*/
/** @typedef {(typeof scales)[number]["value"]} ChartScale */
+5 -8
View File
@@ -2,9 +2,6 @@ import { clamp } from "../math.js";
import { createSvgElement } from "../svg.js";
import { VIEWBOX_WIDTH } from "../viewbox.js";
/** @typedef {import("../highlight.js").SeriesHighlight} SeriesHighlight */
/** @typedef {import("../legend/index.js").Readout} Readout */
const dateFormat = new Intl.DateTimeFormat("en-US", {
day: "2-digit",
month: "2-digit",
@@ -27,7 +24,7 @@ function getPointAtStep(series, step) {
}
/**
* @param {ReturnType<typeof getPointAtStep>[]} points
* @param {ChartPoint[]} points
* @param {number} y
*/
function getClosestPointIndex(points, y) {
@@ -56,8 +53,8 @@ function updateTime(time, date) {
}
/**
* @param {Readout} readout
* @param {ReturnType<typeof getPointAtStep>[]} points
* @param {LegendReadout} readout
* @param {ChartPoint[]} points
* @param {(value: number) => string} format
*/
function updateReadout(readout, points, format) {
@@ -70,7 +67,7 @@ function updateReadout(readout, points, format) {
/**
* @param {SVGSVGElement} svg
* @param {Readout} readout
* @param {LegendReadout} readout
* @param {SeriesHighlight} highlight
* @param {(value: number) => string} format
*/
@@ -231,5 +228,5 @@ export function createScrubber(svg, readout, highlight, format) {
/**
* @typedef {Object} ScrubberSeries
* @property {string} color
* @property {{ date: Date, value: number, x: number, y: number }[]} points
* @property {ChartPoint[]} points
*/
-2
View File
@@ -21,5 +21,3 @@ export function appendSeriesPath(args) {
return path;
}
/** @typedef {import("./highlight.js").SeriesHighlight} SeriesHighlight */
+3 -11
View File
@@ -3,21 +3,16 @@ import { appendSeriesPath } from "../series-path.js";
import { createStackedSeries } from "./series.js";
/**
* @param {SVGGElement} group
* @param {LoadedSeries[]} loadedSeries
* @param {number} height
* @param {SeriesHighlight} highlight
* @param {import("../scale.js").ChartScale} scale
* @param {import("../order.js").ChartOrder} order
* @param {PlotContext} context
*/
export function renderStackedPlot(
export function renderStackedPlot({
group,
loadedSeries,
height,
highlight,
scale,
order,
) {
}) {
const { lineIndexes, plottedSeries, stackIndexes } = createStackedSeries(
loadedSeries,
height,
@@ -51,6 +46,3 @@ export function renderStackedPlot(
return plottedSeries;
}
/** @typedef {import("../highlight.js").SeriesHighlight} SeriesHighlight */
/** @typedef {import("../index.js").LoadedSeries} LoadedSeries */
+3 -20
View File
@@ -37,16 +37,11 @@ function createStackBounds(series, stackOrder, lineIndexes) {
return bounds;
}
/** @returns {StackedPoint[]} */
function createStackedPoints() {
return [];
}
/**
* @param {LoadedSeries[]} loadedSeries
* @param {number} height
* @param {import("../order.js").ChartOrder} order
* @param {import("../scale.js").ChartScale} scale
* @param {ChartOrder} order
* @param {ChartScale} scale
*/
export function createStackedSeries(loadedSeries, height, order, scale) {
const indexes = loadedSeries.map((_, index) => index);
@@ -64,7 +59,7 @@ export function createStackedSeries(loadedSeries, height, order, scale) {
const plottedSeries = loadedSeries.map(({ series, color }) => ({
series,
color,
points: createStackedPoints(),
points: /** @type {StackedPoint[]} */ ([]),
}));
const bounds = createStackBounds(loadedSeries, stackIndexes, lineIndexes);
@@ -116,15 +111,3 @@ export function createStackedSeries(loadedSeries, height, order, scale) {
stackIndexes,
};
}
/** @typedef {import("../index.js").LoadedSeries} LoadedSeries */
/**
* @typedef {Object} StackedPoint
* @property {Date} date
* @property {number} value
* @property {number} x
* @property {number} y
* @property {number} y0
* @property {number} y1
*/
+3 -17
View File
@@ -1,6 +1,6 @@
import { createChartSetting } from "./setting.js";
const timeframes = /** @type {const} */ ({
export const timeframes = /** @type {const} */ ({
"1d": { index: "minute10", count: 144 },
"1w": { index: "hour1", count: 168 },
"1m": { index: "hour4", count: 186 },
@@ -9,7 +9,7 @@ const timeframes = /** @type {const} */ ({
"8y": { index: "week1", count: 418 },
all: { index: "week1" },
});
const options = /** @type {const} */ ([
export const timeframeOptions = /** @type {const} */ ([
{ value: "1d", label: "1d" },
{ value: "1w", label: "1w" },
{ value: "1m", label: "1m" },
@@ -21,7 +21,7 @@ const options = /** @type {const} */ ([
const setting = createChartSetting({
storageKey: "timeframe",
legend: "Time",
options,
options: timeframeOptions,
defaultValue: "all",
});
@@ -58,17 +58,3 @@ export function fetchTimeframe(metric, timeframe) {
? endpoint.last(config.count).fetch()
: endpoint.fetch();
}
/** @typedef {(typeof options)[number]["value"]} TimeframeValue */
/** @typedef {(typeof timeframes)[TimeframeValue]["index"]} TimeframeIndex */
/**
* @typedef {Object} TimeframeEndpoint
* @property {() => Promise<import("./index.js").ChartResult>} fetch
* @property {(count: number) => { fetch: () => Promise<import("./index.js").ChartResult> }} last
*/
/**
* @typedef {Object} TimeframeMetric
* @property {Record<TimeframeIndex, TimeframeEndpoint>} by
*/
+89
View File
@@ -0,0 +1,89 @@
import { brk } from "../../utils/client.js";
import { orders } from "./order.js";
import { scales } from "./scale.js";
import { timeframes, timeframeOptions } from "./timeframes.js";
import { views } from "./views.js";
declare global {
type ChartEntry = {
date: Date;
value: number;
};
type ChartMetric = (client: typeof brk) => TimeframeMetric;
type ChartOrder = (typeof orders)[number]["value"];
type ChartPoint = ChartEntry & {
x: number;
y: number;
};
type ChartResult = {
dateEntries(): Iterable<[Date, number | null | undefined]>;
};
type ChartScale = (typeof scales)[number]["value"];
type ChartSeries = {
label: string;
color: () => string;
role?: "line";
metric: ChartMetric;
};
type ChartUnit = {
id: string;
name: string;
format(value: number): string;
};
type ChartView = (typeof views)[number]["value"];
type Chart = {
title: string;
unit: ChartUnit;
defaultType?: ChartView;
defaultScale?: ChartScale;
series: ChartSeries[];
};
type LegendReadout = {
time: HTMLTimeElement;
rows: { value: HTMLOutputElement }[];
};
type LoadedSeries = {
series: ChartSeries;
color: string;
entries: ChartEntry[];
};
type PlotContext = {
group: SVGGElement;
loadedSeries: LoadedSeries[];
height: number;
highlight: SeriesHighlight;
scale: ChartScale;
order: ChartOrder;
};
type ScaleBounds = {
min: number;
max: number;
minPositive: number;
};
type SeriesHighlight = {
addNode(
node: SVGPathElement | SVGCircleElement,
index: number,
): void;
clearPreview(): void;
clearNodes(): void;
preview(index: number): void;
};
type StackedPoint = ChartPoint & {
y0: number;
y1: number;
};
type TimeframeEndpoint = {
fetch(): Promise<ChartResult>;
last(count: number): { fetch(): Promise<ChartResult> };
};
type TimeframeIndex = (typeof timeframes)[TimeframeValue]["index"];
type TimeframeMetric = {
by: Record<TimeframeIndex, TimeframeEndpoint>;
};
type TimeframeValue = (typeof timeframeOptions)[number]["value"];
}
export {};
-3
View File
@@ -8,6 +8,3 @@ export const units = /** @type {const} */ ({
utxos: { id: "utxos", name: "UTXOs", format: formatNumberValue },
usd: { id: "usd", name: "US Dollars", format: formatNumberValue },
});
/** @typedef {keyof typeof units} ChartUnitKey */
/** @typedef {typeof units[ChartUnitKey]} ChartUnit */
+1 -3
View File
@@ -1,6 +1,6 @@
import { createChartSetting } from "./setting.js";
const views = /** @type {const} */ ([
export const views = /** @type {const} */ ([
{ value: "line", label: "Line" },
{ value: "area", label: "Area" },
{ value: "stacked", label: "Stack" },
@@ -38,5 +38,3 @@ export function saveView(chartKey, view) {
export function createViewControl(currentView, onChange) {
return setting.create(currentView, onChange);
}
/** @typedef {(typeof views)[number]["value"]} ChartView */
+2 -9
View File
@@ -1,7 +1,7 @@
import { createPathId } from "../path.js";
/**
* @param {Section} section
* @param {LearnSection} section
* @param {readonly string[]} path
*/
function createContentsItem(section, path) {
@@ -27,7 +27,7 @@ function createContentsItem(section, path) {
return item;
}
/** @param {Section[]} sections */
/** @param {LearnSection[]} sections */
export function createContents(sections) {
const nav = document.createElement("nav");
const list = document.createElement("ol");
@@ -41,10 +41,3 @@ export function createContents(sections) {
nav.append(list);
return nav;
}
/**
* @typedef {Object} Section
* @property {string} title
* @property {boolean} [numbered]
* @property {Section[]} [children]
*/
+2 -5
View File
@@ -26,7 +26,7 @@ function colorAt(index) {
return palette[index % palette.length];
}
/** @param {readonly { label: string, color?: ChartColor, metric: Metric }[]} items */
/** @param {readonly { label: string, color?: () => string, metric: ChartMetric }[]} items */
export function createCohortSeries(items) {
return items.map(({ label, color, metric }, index) => ({
label,
@@ -38,7 +38,7 @@ export function createCohortSeries(items) {
/**
* @template {string} Key
* @param {readonly (readonly [string, Key])[]} items
* @param {(key: Key) => Metric} createMetric
* @param {(key: Key) => ChartMetric} createMetric
*/
export function createCohortSeriesFromKeys(items, createMetric) {
return createCohortSeries(
@@ -48,6 +48,3 @@ export function createCohortSeriesFromKeys(items, createMetric) {
})),
);
}
/** @typedef {import("../charts/index.js").ChartSeries["color"]} ChartColor */
/** @typedef {import("../charts/index.js").ChartSeries["metric"]} Metric */
+1 -3
View File
@@ -24,7 +24,7 @@ function createPools(pools) {
}
/**
* @param {(window: WindowKey) => TimeframeMetric} createMetric
* @param {(window: RollingWindowKey) => TimeframeMetric} createMetric
*/
function createWindowSeries(createMetric) {
return createRollingWindowSeries((window) => () => createMetric(window));
@@ -102,7 +102,5 @@ export function createMinorPoolBlocksMinedSeries(pool) {
);
}
/** @typedef {import("./rolling-windows.js").RollingWindowKey} WindowKey */
/** @typedef {typeof brk.series.pools.major.unknown} MajorPool */
/** @typedef {typeof brk.series.pools.minor.blockfills} MinorPool */
/** @typedef {import("../charts/timeframes.js").TimeframeMetric} TimeframeMetric */
+2 -5
View File
@@ -1,14 +1,14 @@
import { createCohortSeries } from "./cohort-series.js";
import { colors } from "../../utils/colors.js";
const rollingWindows = /** @type {const} */ ([
export const rollingWindows = /** @type {const} */ ([
["24h", "_24h", colors.sky],
["1w", "_1w", colors.cyan],
["1m", "_1m", colors.blue],
["1y", "_1y", colors.violet],
]);
/** @param {(key: RollingWindowKey) => Metric} createMetric */
/** @param {(key: RollingWindowKey) => ChartMetric} createMetric */
export function createRollingWindowSeries(createMetric) {
return createCohortSeries(
rollingWindows.map(([label, key, color]) => ({
@@ -18,6 +18,3 @@ export function createRollingWindowSeries(createMetric) {
})),
);
}
/** @typedef {(typeof rollingWindows)[number][1]} RollingWindowKey */
/** @typedef {import("./cohort-series.js").Metric} Metric */
+7
View File
@@ -0,0 +1,7 @@
import { rollingWindows } from "./rolling-windows.js";
declare global {
type RollingWindowKey = (typeof rollingWindows)[number][1];
}
export {};
+3 -12
View File
@@ -1,12 +1,12 @@
import { createContents } from "./contents/index.js";
import { sections } from "./data/index.js";
import { createChart as createDataChart } from "./charts/index.js";
import { createChart } from "./charts/index.js";
import { initHashLinks } from "./hash-links.js";
import { initScrollSpy } from "./scroll-spy.js";
import { createPathId } from "./path.js";
/**
* @param {Section} section
* @param {LearnSection} section
* @param {readonly string[]} [path]
*/
function createSection(section, path = []) {
@@ -26,7 +26,7 @@ function createSection(section, path = []) {
heading.append(anchor);
description.append(section.description);
element.append(heading, description);
if (section.chart) element.append(createDataChart(section.chart, id));
if (section.chart) element.append(createChart(section.chart, id));
for (const child of children) {
element.append(createSection(child, sectionPath));
@@ -49,12 +49,3 @@ export function createLearnPage() {
initScrollSpy(main);
return main;
}
/**
* @typedef {Object} Section
* @property {string} title
* @property {string} description
* @property {import("./charts/index.js").Chart} [chart]
* @property {boolean} [numbered]
* @property {Section[]} [children]
*/
+11
View File
@@ -0,0 +1,11 @@
declare global {
type LearnSection = {
title: string;
description: string;
chart?: Chart;
numbered?: boolean;
children?: LearnSection[];
};
}
export {};