diff --git a/website_next/learn/charts/area/index.js b/website_next/learn/charts/area/index.js index 7721abda3..ab1ab3cad 100644 --- a/website_next/learn/charts/area/index.js +++ b/website_next/learn/charts/area/index.js @@ -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 */ diff --git a/website_next/learn/charts/bar/index.js b/website_next/learn/charts/bar/index.js index 1a1c6cd71..b836d7c7c 100644 --- a/website_next/learn/charts/bar/index.js +++ b/website_next/learn/charts/bar/index.js @@ -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 */ diff --git a/website_next/learn/charts/dots/index.js b/website_next/learn/charts/dots/index.js index 9fe6a78c1..7d92e39e3 100644 --- a/website_next/learn/charts/dots/index.js +++ b/website_next/learn/charts/dots/index.js @@ -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 */ diff --git a/website_next/learn/charts/highlight.js b/website_next/learn/charts/highlight.js index 1f7fac22c..a57b20de1 100644 --- a/website_next/learn/charts/highlight.js +++ b/website_next/learn/charts/highlight.js @@ -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 - */ diff --git a/website_next/learn/charts/index.js b/website_next/learn/charts/index.js index 311d561e9..34943b56c 100644 --- a/website_next/learn/charts/index.js +++ b/website_next/learn/charts/index.js @@ -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 - */ diff --git a/website_next/learn/charts/legend/index.js b/website_next/learn/charts/legend/index.js index a08b15792..a6888df9d 100644 --- a/website_next/learn/charts/legend/index.js +++ b/website_next/learn/charts/legend/index.js @@ -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 */ diff --git a/website_next/learn/charts/line/index.js b/website_next/learn/charts/line/index.js index cb8a440ff..dc7409ae5 100644 --- a/website_next/learn/charts/line/index.js +++ b/website_next/learn/charts/line/index.js @@ -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 */ diff --git a/website_next/learn/charts/line/series.js b/website_next/learn/charts/line/series.js index 059d53028..61e8279bc 100644 --- a/website_next/learn/charts/line/series.js +++ b/website_next/learn/charts/line/series.js @@ -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 */ diff --git a/website_next/learn/charts/loader.js b/website_next/learn/charts/loader.js index 45085462a..9241c4db9 100644 --- a/website_next/learn/charts/loader.js +++ b/website_next/learn/charts/loader.js @@ -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 */ diff --git a/website_next/learn/charts/order.js b/website_next/learn/charts/order.js index 13af19886..89a231a7f 100644 --- a/website_next/learn/charts/order.js +++ b/website_next/learn/charts/order.js @@ -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 */ diff --git a/website_next/learn/charts/path.js b/website_next/learn/charts/path.js index 1bfa1558b..f225e0e8e 100644 --- a/website_next/learn/charts/path.js +++ b/website_next/learn/charts/path.js @@ -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), diff --git a/website_next/learn/charts/plot.js b/website_next/learn/charts/plot.js index 8b9a07f68..81002fc19 100644 --- a/website_next/learn/charts/plot.js +++ b/website_next/learn/charts/plot.js @@ -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 */ diff --git a/website_next/learn/charts/renderer.js b/website_next/learn/charts/renderer.js index 6870a7db1..c57a584fb 100644 --- a/website_next/learn/charts/renderer.js +++ b/website_next/learn/charts/renderer.js @@ -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 */ diff --git a/website_next/learn/charts/scale.js b/website_next/learn/charts/scale.js index 4c12a7bce..663eba3b2 100644 --- a/website_next/learn/charts/scale.js +++ b/website_next/learn/charts/scale.js @@ -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 */ diff --git a/website_next/learn/charts/scrubber/index.js b/website_next/learn/charts/scrubber/index.js index 46c5840ec..08acdda28 100644 --- a/website_next/learn/charts/scrubber/index.js +++ b/website_next/learn/charts/scrubber/index.js @@ -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[]} points + * @param {ChartPoint[]} points * @param {number} y */ function getClosestPointIndex(points, y) { @@ -56,8 +53,8 @@ function updateTime(time, date) { } /** - * @param {Readout} readout - * @param {ReturnType[]} 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 */ diff --git a/website_next/learn/charts/series-path.js b/website_next/learn/charts/series-path.js index 2512fc1eb..fa97eee89 100644 --- a/website_next/learn/charts/series-path.js +++ b/website_next/learn/charts/series-path.js @@ -21,5 +21,3 @@ export function appendSeriesPath(args) { return path; } - -/** @typedef {import("./highlight.js").SeriesHighlight} SeriesHighlight */ diff --git a/website_next/learn/charts/stacked/index.js b/website_next/learn/charts/stacked/index.js index bc3df5e1b..9475e3d69 100644 --- a/website_next/learn/charts/stacked/index.js +++ b/website_next/learn/charts/stacked/index.js @@ -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 */ diff --git a/website_next/learn/charts/stacked/series.js b/website_next/learn/charts/stacked/series.js index d153b658a..5aa0014ab 100644 --- a/website_next/learn/charts/stacked/series.js +++ b/website_next/learn/charts/stacked/series.js @@ -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 - */ diff --git a/website_next/learn/charts/timeframes.js b/website_next/learn/charts/timeframes.js index 4d498bfce..628d40332 100644 --- a/website_next/learn/charts/timeframes.js +++ b/website_next/learn/charts/timeframes.js @@ -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} fetch - * @property {(count: number) => { fetch: () => Promise }} last - */ - -/** - * @typedef {Object} TimeframeMetric - * @property {Record} by - */ diff --git a/website_next/learn/charts/types.d.ts b/website_next/learn/charts/types.d.ts new file mode 100644 index 000000000..d3cfea8bf --- /dev/null +++ b/website_next/learn/charts/types.d.ts @@ -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; + last(count: number): { fetch(): Promise }; + }; + type TimeframeIndex = (typeof timeframes)[TimeframeValue]["index"]; + type TimeframeMetric = { + by: Record; + }; + type TimeframeValue = (typeof timeframeOptions)[number]["value"]; +} + +export {}; diff --git a/website_next/learn/charts/units.js b/website_next/learn/charts/units.js index 07e8e22f8..e549c56ca 100644 --- a/website_next/learn/charts/units.js +++ b/website_next/learn/charts/units.js @@ -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 */ diff --git a/website_next/learn/charts/views.js b/website_next/learn/charts/views.js index e481d29e9..c4e240dd2 100644 --- a/website_next/learn/charts/views.js +++ b/website_next/learn/charts/views.js @@ -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 */ diff --git a/website_next/learn/contents/index.js b/website_next/learn/contents/index.js index 35b2794aa..7c31aa2d0 100644 --- a/website_next/learn/contents/index.js +++ b/website_next/learn/contents/index.js @@ -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] - */ diff --git a/website_next/learn/data/cohort-series.js b/website_next/learn/data/cohort-series.js index 37198f9a1..84aba94f7 100644 --- a/website_next/learn/data/cohort-series.js +++ b/website_next/learn/data/cohort-series.js @@ -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 */ diff --git a/website_next/learn/data/mining-pools.js b/website_next/learn/data/mining-pools.js index f5a14079c..21ee198e8 100644 --- a/website_next/learn/data/mining-pools.js +++ b/website_next/learn/data/mining-pools.js @@ -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 */ diff --git a/website_next/learn/data/rolling-windows.js b/website_next/learn/data/rolling-windows.js index da92a6c49..24723c376 100644 --- a/website_next/learn/data/rolling-windows.js +++ b/website_next/learn/data/rolling-windows.js @@ -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 */ diff --git a/website_next/learn/data/types.d.ts b/website_next/learn/data/types.d.ts new file mode 100644 index 000000000..d9918b69c --- /dev/null +++ b/website_next/learn/data/types.d.ts @@ -0,0 +1,7 @@ +import { rollingWindows } from "./rolling-windows.js"; + +declare global { + type RollingWindowKey = (typeof rollingWindows)[number][1]; +} + +export {}; diff --git a/website_next/learn/index.js b/website_next/learn/index.js index e5966d9c2..717bc9bf3 100644 --- a/website_next/learn/index.js +++ b/website_next/learn/index.js @@ -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] - */ diff --git a/website_next/learn/types.d.ts b/website_next/learn/types.d.ts new file mode 100644 index 000000000..d3c889720 --- /dev/null +++ b/website_next/learn/types.d.ts @@ -0,0 +1,11 @@ +declare global { + type LearnSection = { + title: string; + description: string; + chart?: Chart; + numbered?: boolean; + children?: LearnSection[]; + }; +} + +export {};