diff --git a/website/index.html b/website/index.html index 2e50731db..4c4878329 100644 --- a/website/index.html +++ b/website/index.html @@ -968,76 +968,135 @@ pointer-events: none; } - .chart > .panes { - position: relative; + .chart { display: flex; flex-direction: column; - flex: 1; min-height: 0; - > .pane { - z-index: 20; - position: relative; - min-height: 0px; - width: 100%; - cursor: crosshair; - height: 100%; + > legend { + display: flex; + align-items: center; + gap: 1.5rem; + margin-left: var(--negative-main-padding); + margin-right: var(--negative-main-padding); + padding-left: var(--main-padding); + padding-right: var(--main-padding); + padding-bottom: 1.25rem; + overflow-x: auto; + min-width: 0; - &:has(+ .chart-wrapper:not([hidden])) { - height: calc(100% - 62px); - } - - > fieldset { - pointer-events: none; - position: absolute; - left: 0px; - top: 0px; - z-index: 10; + > div { + flex: 0; display: flex; align-items: center; - font-size: var(--font-size-xs); - line-height: var(--line-height-xs); - gap: 0.5rem; - > div.field { + > label { + margin: -0.375rem 0; + color: var(--color); + + > span { + display: flex !important; + } + + &:has(input:not(:checked)) { + color: var(--off-color); + + > span.main > span.name { + text-decoration-thickness: 1.5px; + text-decoration-color: var(--color); + text-decoration-line: line-through; + } + + &:hover { + * { + color: var(--off-color) !important; + } + + > span.main > span.name { + text-decoration-color: var(--orange) !important; + } + } + } + } + + > a { + padding: 0.375rem; + margin: -0.375rem; + } + } + } + + > .panes { + position: relative; + display: flex; + flex-direction: column; + flex: 1; + min-height: 0; + + > .pane { + z-index: 20; + position: relative; + min-height: 0px; + width: 100%; + cursor: crosshair; + height: 100%; + + &:has(+ .chart-wrapper:not([hidden])) { + height: calc(100% - 62px); + } + + > fieldset { + pointer-events: none; + position: absolute; + left: 0px; + top: 0px; + z-index: 10; display: flex; align-items: center; font-size: var(--font-size-xs); line-height: var(--line-height-xs); gap: 0.5rem; - > legend, - > div { - flex-shrink: 0; - } - - > hr { - min-width: 1rem; - } - - label { - padding: 0.5rem; - margin: -0.5rem; - } - - > div { + > div.field { display: flex; + align-items: center; + font-size: var(--font-size-xs); + line-height: var(--line-height-xs); gap: 0.5rem; + + > legend, + > div { + flex-shrink: 0; + } + + > hr { + min-width: 1rem; + } + + label { + padding: 0.5rem; + margin: -0.5rem; + } + + > div { + display: flex; + gap: 0.5rem; + } } } + + > .lightweight-chart { + height: 100%; + margin-right: var(--negative-main-padding); + } } - > .lightweight-chart { - height: 100%; - margin-right: var(--negative-main-padding); + > .shadow-bottom { + bottom: 1.75rem; + width: 80px; + left: auto; } } - - > .shadow-bottom { - bottom: 1.75rem; - width: 80px; - left: auto; - } } diff --git a/website/packages/lightweight-charts/types.d.ts b/website/packages/lightweight-charts/types.d.ts new file mode 100644 index 000000000..a15bd5132 --- /dev/null +++ b/website/packages/lightweight-charts/types.d.ts @@ -0,0 +1,122 @@ +import { Signal } from "../solid-signals/types"; +import { Accessor } from "../solid-signals/2024-11-02/types/signals"; +import { Owner } from "../solid-signals/2024-11-02/types/core/owner"; +import { + DeepPartial, + BaselineStyleOptions, + CandlestickStyleOptions, + LineStyleOptions, + SeriesOptionsCommon, + Time, + CandlestickData, + ISeriesApi, + BaselineData, +} from "./v4.2.0/types"; +import { Color } from "../../scripts/types/self"; + +interface BaseSeriesBlueprint { + title: string; + defaultActive?: boolean; +} +interface BaselineSeriesBlueprint extends BaseSeriesBlueprint { + type: "Baseline"; + color?: Color; + options?: DeepPartial; + data?: Accessor[]>; +} +interface CandlestickSeriesBlueprint extends BaseSeriesBlueprint { + type: "Candlestick"; + color?: Color; + options?: DeepPartial; + data?: Accessor[]>; +} +interface LineSeriesBlueprint extends BaseSeriesBlueprint { + type?: "Line"; + color: Color; + options?: DeepPartial; + data?: Accessor[]>; +} +type AnySpecificSeriesBlueprint = + | BaselineSeriesBlueprint + | CandlestickSeriesBlueprint + | LineSeriesBlueprint; + +type SeriesType = NonNullable; +type PriceSeriesType = "Candlestick" | "Line"; + +type RemoveSeriesBlueprintFluff = + Omit; + +type SplitSeriesBlueprint = { + datasetPath: AnyDatasetPath; + main?: boolean; +} & AnySpecificSeriesBlueprint; + +type SingleSeriesBlueprint = AnySpecificSeriesBlueprint; + +interface CreateBaseSeriesParameters extends BaseSeriesBlueprint { + id: string; + disabled?: Accessor; + color?: Color; +} +interface BaseSeries { + id: string; + title: string; + color: Color | Color[]; + active: Signal; + visible: Accessor; + disabled: Accessor; +} +interface SingleSeries extends BaseSeries { + iseries: ISeriesApi; +} +interface SplitSeries extends BaseSeries { + chunks: Array | undefined>>; + dataset: ResourceDataset; +} + +interface CreateSingleSeriesParameters { + blueprint: SingleSeriesBlueprint; + id: string; +} + +interface CreateSplitSeriesParameters { + dataset: ResourceDataset; + blueprint: SplitSeriesBlueprint; + id: string; + index: number; + setMinMaxMarkersWhenIdle: VoidFunction; + disabled?: Accessor; +} + +type ChartPane = IChartApi & { + whitespace: ISeriesApi<"Line">; + hidden: () => boolean; + setHidden: (b: boolean) => void; + setInitialVisibleTimeRange: VoidFunction; + createSingleSeries: (a: CreateSingleSeriesParameters) => SingleSeries; + createSplitSeries: ( + a: CreateSplitSeriesParameters, + ) => SplitSeries; + splitSeries: SplitSeries[]; +}; + +interface CreatePaneParameters { + unit: Unit; + paneIndex?: number; + whitespace?: true; + options?: DeepPartial; + config?: SingleSeriesBlueprint[]; +} + +interface Marker { + weight: number; + time: Time; + value: number; + seriesChunk: ISeriesApi; +} + +interface HoveredLegend { + label: HTMLLabelElement; + series: SingleSeries | SplitSeries; +} diff --git a/website/packages/lightweight-charts/wrapper.js b/website/packages/lightweight-charts/wrapper.js index 957906815..1a6722496 100644 --- a/website/packages/lightweight-charts/wrapper.js +++ b/website/packages/lightweight-charts/wrapper.js @@ -357,6 +357,7 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { * @param {TimeScale} param0.scale * @param {"static" | "moveable"} param0.kind * @param {Utilities} param0.utils + * @param {Owner | null} [param0.owner] * @param {CreatePaneParameters[]} [param0.config] */ function createChart({ @@ -368,7 +369,13 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { scale, config, utils, + owner: _owner, }) { + /** @type {SplitSeries[]} */ + const chartSplitSeries = []; + + let owner = _owner || signals.getOwner(); + const div = window.document.createElement("div"); div.classList.add("chart"); parent.append(div); @@ -541,14 +548,14 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { inputName: utils.stringToId(`selected-${series.title}-${extraName}`), inputValue: "value", labelTitle: "Click to toggle", - onClick: (event) => { - event.preventDefault(); - event.stopPropagation(); - input.checked = !input.checked; + onClick: () => { series.active.set(input.checked); }, + type: "solo", }); + input.checked = series.active(); + const spanMain = window.document.createElement("span"); spanMain.classList.add("main"); label.append(spanMain); @@ -568,10 +575,6 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { hoveredLegend.set(undefined); }); - signals.createEffect(series.active, (checked) => { - input.checked = checked; - }); - function shouldHighlight() { const hovered = hoveredLegend(); return ( @@ -680,7 +683,7 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { } } else { applySeriesOption({ - series: series.series, + series: series.iseries, hovered, }); } @@ -727,6 +730,9 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { chartDiv.classList.add("lightweight-chart"); chartWrapper.append(chartDiv); + /** @type {SplitSeries[]} */ + const paneSplitSeries = []; + options = { ...options }; if (kind === "static") { options.handleScale = false; @@ -748,9 +754,9 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { }); /** - * @param {CreateBaselineSeriesParams} args + * @param {RemoveSeriesBlueprintFluff} args */ - function createBaseLineSeries({ color, options, owner, data }) { + function createBaseLineSeries({ color, options, data }) { const topLineColor = color || colors.profit; const bottomLineColor = color || colors.loss; @@ -784,16 +790,20 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { }); if (data) { - series.setData(data); + signals.runWithOwner(owner, () => { + signals.createEffect(data, (data) => { + series.setData(data); + }); + }); } return series; } /** - * @param {CreateCandlestickSeriesParams} args + * @param {RemoveSeriesBlueprintFluff} args */ - function createCandlestickSeries({ options, owner, data }) { + function createCandlestickSeries({ options, data }) { function computeColors() { const upColor = colors.profit(); const downColor = colors.loss(); @@ -825,16 +835,20 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { }); if (data) { - series.setData(data); + signals.runWithOwner(owner, () => { + signals.createEffect(data, (data) => { + series.setData(data); + }); + }); } return series; } /** - * @param {CreateLineSeriesParams} args + * @param {RemoveSeriesBlueprintFluff} args */ - function createLineSeries({ color, options, owner, data }) { + function createLineSeries({ color, options, data }) { function computeColors() { return { color: color(), @@ -847,49 +861,41 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { ...computeColors(), }); - if (data) { - series.setData(data); - } - signals.runWithOwner(owner, () => { signals.createEffect(computeColors, (computeColors) => { series.applyOptions(computeColors); }); }); + if (data) { + signals.runWithOwner(owner, () => { + signals.createEffect(data, (data) => { + series.setData(data); + }); + }); + } + return series; } /** * @template {TimeScale} S - * @param {CreateSplitSeriesParameters} args + * @param {CreateBaseSeriesParameters} args */ - function createSplitSeries({ - option, - index: seriesIndex, + function createBaseSeries({ + id, disabled: _disabled, - setMinMaxMarkersWhenIdle, - dataset, - seriesBlueprint, - splitSeries, + title, + color, + defaultActive, }) { - const { - title, - color, - defaultActive, - type, - options: seriesOptions, - } = seriesBlueprint; - - /** @type {Signal | undefined>[]} */ - const chunks = new Array(dataset.fetchedJSONs.length); - - const id = utils.stringToId(title); - const storageId = utils.stringToId(`${option.id}-${title}`); + const keyPrefix = id; + const paramKey = utils.stringToId(title); + const storageKey = `${keyPrefix}-${paramKey}`; const active = signals.createSignal( - utils.url.readBoolParam(id) ?? - utils.storage.readBool(storageId) ?? + utils.url.readBoolParam(paramKey) ?? + utils.storage.readBool(storageKey) ?? defaultActive ?? true, ); @@ -898,12 +904,10 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { const visible = signals.createMemo(() => active() && !disabled()); - /** @satisfies {SplitSeries} */ + /** @satisfies {BaseSeries} */ const series = { active, - chunks, color: color || [colors.profit, colors.loss], - dataset, disabled, id, title, @@ -918,32 +922,97 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { } if (active !== (defaultActive || true)) { - utils.url.writeParam(id, active); - utils.storage.write(storageId, active); + utils.url.writeParam(paramKey, active); + utils.storage.write(storageKey, active); } else { - utils.url.removeParam(id); - utils.storage.remove(storageId); + utils.url.removeParam(paramKey); + utils.storage.remove(storageKey); } }, ); - splitSeries.push(series); + return series; + } - const owner = signals.getOwner(); + const chartPane = /** @type {ChartPane} */ (_chart); + + chartPane.createSingleSeries = function ({ blueprint, id }) { + /** @type {ISeriesApi} */ + let s; + + switch (blueprint.type) { + case "Baseline": { + s = createBaseLineSeries(blueprint); + break; + } + case "Candlestick": { + s = createCandlestickSeries(blueprint); + break; + } + default: + case "Line": { + s = createLineSeries(blueprint); + break; + } + } + + /** @satisfies {SingleSeries} */ + const series = { + ...createBaseSeries({ + id, + title: blueprint.title, + color: blueprint.color, + defaultActive: blueprint.defaultActive, + }), + iseries: s, + }; + + signals.createEffect(series.visible, (visible) => { + series.iseries.applyOptions({ + visible, + }); + }); + + createLegend({ series }); + + return series; + }; + chartPane.createSplitSeries = function ({ + id, + index: seriesIndex, + disabled, + setMinMaxMarkersWhenIdle, + dataset, + blueprint, + }) { + /** @satisfies {SplitSeries} */ + const series = { + ...createBaseSeries({ + id, + title: blueprint.title, + color: blueprint.color, + defaultActive: blueprint.defaultActive, + disabled, + }), + dataset, + chunks: new Array(dataset.fetchedJSONs.length), + }; + + paneSplitSeries.push(series); + chartSplitSeries.unshift(series); dataset.fetchedJSONs.forEach((json, index) => { const chunk = signals.createSignal( /** @type {ISeriesApi | undefined} */ (undefined), ); - chunks[index] = chunk; + series.chunks[index] = chunk; const isMyTurn = signals.createMemo(() => { if (seriesIndex <= 0) return true; - const previousSeriesChunk = splitSeries.at(seriesIndex - 1)?.chunks[ - index - ]; + const previousSeriesChunk = paneSplitSeries.at(seriesIndex - 1) + ?.chunks[index]; const isPreviousSeriesOnChart = previousSeriesChunk?.(); return !!isPreviousSeriesOnChart; @@ -957,28 +1026,25 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { let s = chunk(); if (!s) { - switch (type) { + switch (blueprint.type) { case "Baseline": { s = createBaseLineSeries({ - color, - options: seriesOptions, - owner, + color: blueprint.color, + options: blueprint.options, }); break; } case "Candlestick": { s = createCandlestickSeries({ - options: seriesOptions, - owner, + options: blueprint.options, }); break; } default: case "Line": { s = createLineSeries({ - color, - options: seriesOptions, - owner, + color: blueprint.color, + options: blueprint.options, }); break; } @@ -1069,23 +1135,17 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { }); }); - createLegend({ series, extraName: type }); + createLegend({ series, extraName: blueprint.type }); return series; - } - - const chartPane = /** @type {ChartPane} */ (_chart); - - chartPane.createSplitSeries = createSplitSeries; - chartPane.createBaseLineSeries = createBaseLineSeries; - chartPane.createCandlesticksSeries = createCandlestickSeries; - chartPane.createLineSeries = createLineSeries; + }; chartPane.hidden = () => { return chartWrapper.hidden; }; chartPane.setHidden = (b) => { chartWrapper.hidden = b; }; + chartPane.splitSeries = paneSplitSeries; chartPane.setInitialVisibleTimeRange = () => { const range = visibleTimeRange(); @@ -1143,26 +1203,15 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { } createUnitAndModeElements(); - config?.forEach((params) => { - // createLegend(params); - switch (params.kind) { - case "line": { - chartPane.createLineSeries(params); - break; - } - case "candle": { - chartPane.createCandlesticksSeries(params); - break; - } - case "baseline": { - chartPane.createBaseLineSeries(params); - break; - } - } - }); - switch (kind) { case "static": { + config?.forEach((params) => { + chartPane.createSingleSeries({ + id: utils.stringToId(params.title), + blueprint: params, + }); + }); + chartPane.timeScale().fitContent(); break; @@ -1199,9 +1248,11 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { * * @param {Object} param0 * @param {TimeScale} param0.scale + * @param {Owner | null} param0.owner */ - function reset({ scale: _scale }) { + function reset({ scale: _scale, owner: _owner }) { scale = _scale; + owner = _owner; panes.forEach((pane) => pane.remove()); panes.length = 0; legendElement.innerHTML = ""; @@ -1265,6 +1316,7 @@ export default import("./v4.2.0/script.js").then((lightweightCharts) => { saveVisibleRange, getTicksToWidthRatio, debouncedSaveVisibleRange, + splitSeries: chartSplitSeries, }; } diff --git a/website/packages/solid-signals/wrapper.js b/website/packages/solid-signals/wrapper.js index 462d16e11..c7153a4a9 100644 --- a/website/packages/solid-signals/wrapper.js +++ b/website/packages/solid-signals/wrapper.js @@ -33,7 +33,7 @@ const importSignals = import("./2024-11-02/script.js").then((_signals) => { /** * @template T * @param {T} initialValue - * @param {SignalOptions & {save?: {id?: string; param?: string; serialize: (v: NonNullable) => string; deserialize: (v: string) => NonNullable}}} [options] + * @param {SignalOptions & {save?: {keyPrefix: string; key: string; serialize: (v: NonNullable) => string; deserialize: (v: string) => NonNullable}}} [options] * @returns {Signal} */ createSignal(initialValue, options) { @@ -51,14 +51,14 @@ const importSignals = import("./2024-11-02/script.js").then((_signals) => { if (options?.save) { const save = options.save; + const paramKey = save.key; + const storageKey = `${save.keyPrefix}-${paramKey}`; + let serialized = /** @type {string | null} */ (null); - if (save.param) { - serialized = new URLSearchParams(window.location.search).get( - save.param, - ); - } - if (serialized === null && save.id) { - serialized = localStorage.getItem(save.id); + serialized = new URLSearchParams(window.location.search).get(paramKey); + + if (serialized === null) { + serialized = localStorage.getItem(storageKey); } if (serialized) { set(save.deserialize(serialized)); @@ -68,7 +68,7 @@ const importSignals = import("./2024-11-02/script.js").then((_signals) => { this.createEffect(get, (value) => { if (!save) return; - if (!firstEffect && save.id) { + if (!firstEffect) { if ( value !== undefined && value !== null && @@ -76,24 +76,22 @@ const importSignals = import("./2024-11-02/script.js").then((_signals) => { initialValue === null || save.serialize(value) !== save.serialize(initialValue)) ) { - localStorage.setItem(save.id, save.serialize(value)); + localStorage.setItem(storageKey, save.serialize(value)); } else { - localStorage.removeItem(save.id); + localStorage.removeItem(storageKey); } } - if (save.param) { - if ( - value !== undefined && - value !== null && - (initialValue === undefined || - initialValue === null || - save.serialize(value) !== save.serialize(initialValue)) - ) { - writeParam(save.param, save.serialize(value)); - } else { - removeParam(save.param); - } + if ( + value !== undefined && + value !== null && + (initialValue === undefined || + initialValue === null || + save.serialize(value) !== save.serialize(initialValue)) + ) { + writeParam(paramKey, save.serialize(value)); + } else { + removeParam(paramKey); } firstEffect = false; diff --git a/website/scripts/chart.js b/website/scripts/chart.js index bc29719d0..8e19dc2ba 100644 --- a/website/scripts/chart.js +++ b/website/scripts/chart.js @@ -1,8 +1,7 @@ // @ts-check /** - * @import { ChartPane, HoveredLegend, PriceSeriesType, SplitSeries } from "./types/self" - * @import { Options } from './options'; + * @import { PriceSeriesType } from '../packages/lightweight-charts/types'; */ /** @@ -110,14 +109,12 @@ export function init({ * @param {VoidFunction} args.setMinMaxMarkersWhenIdle * @param {Option} args.option * @param {ChartPane} args.chartPane - * @param {SplitSeries[]} args.chartSeries */ function createPriceSeries({ type, setMinMaxMarkersWhenIdle, option, chartPane, - chartSeries: splitSeries, }) { const s = scale(); @@ -131,17 +128,17 @@ export function init({ const title = "BTC Price"; - /** @type {SeriesBlueprint} */ - let seriesBlueprint; + /** @type {SplitSeriesBlueprint} */ + let blueprint; if (type === "Candlestick") { - seriesBlueprint = { + blueprint = { datasetPath, title, type: "Candlestick", }; } else { - seriesBlueprint = { + blueprint = { datasetPath, title, color: colors.default, @@ -151,11 +148,10 @@ export function init({ const disabled = signals.createMemo(() => priceSeriesType() !== type); const priceSeries = chartPane.createSplitSeries({ - seriesBlueprint, + blueprint, dataset, - option, + id: option.id, index: -1, - splitSeries, disabled, setMinMaxMarkersWhenIdle, }); @@ -199,9 +195,6 @@ export function init({ (list) => (list ? [list] : []), ); - /** @type {SplitSeries[]} */ - const allSeries = []; - chartsBlueprints.map((seriesBlueprints, paneIndex) => { const chartPane = chart.createPane({ paneIndex, @@ -209,9 +202,6 @@ export function init({ whitespace: true, }); - /** @type {SplitSeries[]} */ - const splitSeries = []; - function setMinMaxMarkers() { try { const { from, to } = chart.visibleTimeRange(); @@ -226,8 +216,8 @@ export function init({ const ids = chart.visibleDatasetIds(); - for (let i = 0; i < splitSeries.length; i++) { - const { chunks, dataset } = splitSeries[i]; + for (let i = 0; i < chartPane.splitSeries.length; i++) { + const { chunks, dataset } = chartPane.splitSeries[i]; for (let j = 0; j < ids.length; j++) { const id = ids[j]; @@ -370,7 +360,6 @@ export function init({ function _createPriceSeries(type) { return createPriceSeries({ chartPane, - chartSeries: splitSeries, option, setMinMaxMarkersWhenIdle, type, @@ -392,21 +381,17 @@ export function init({ createLinkPriceSeriesEffect(); } - [...seriesBlueprints].reverse().forEach((seriesBlueprint, index) => { - const dataset = datasets.getOrCreate( - scale, - seriesBlueprint.datasetPath, - ); + [...seriesBlueprints].reverse().forEach((blueprint, index) => { + const dataset = datasets.getOrCreate(scale, blueprint.datasetPath); // Don't trigger reactivity by design activeDatasets().add(dataset); chartPane.createSplitSeries({ index, - seriesBlueprint, - option, + blueprint, + id: option.id, setMinMaxMarkersWhenIdle, - splitSeries, dataset, }); }); @@ -415,16 +400,14 @@ export function init({ activeDatasets.set((s) => s); - splitSeries.forEach((series) => { - allSeries.unshift(series); - + chartPane.splitSeries.forEach((series) => { signals.createEffect(series.active, () => { setMinMaxMarkersWhenIdle(); }); }); const chartVisible = signals.createMemo(() => - splitSeries.some((series) => series.visible()), + chartPane.splitSeries.some((series) => series.visible()), ); function createChartVisibilityEffect() { @@ -504,7 +487,7 @@ export function init({ function createApplyChartOptionEffect() { signals.createEffect(selected, (option) => { - chart.reset({ scale: option.scale }); + chart.reset({ scale: option.scale, owner: signals.getOwner() }); applyChartOption(option); }); } diff --git a/website/scripts/main.js b/website/scripts/main.js index 8d3fc22ec..ec5765f04 100644 --- a/website/scripts/main.js +++ b/website/scripts/main.js @@ -1,8 +1,9 @@ // @ts-check /** - * @import { Option, ResourceDataset, TimeScale, TimeRange, Unit, Marker, Weighted, DatasetPath, OHLC, FetchedJSON, DatasetValue, FetchedResult, AnyDatasetPath, SeriesBlueprint, BaselineSpecificSeriesBlueprint, CandlestickSpecificSeriesBlueprint, LineSpecificSeriesBlueprint, SpecificSeriesBlueprintWithChart, Color, DatasetCandlestickData, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, AnyPath, SimulationOption, Frequency, CreatePaneParameters, CreateBaselineSeriesParams, CreateCandlestickSeriesParams, CreateLineSeriesParams, LastValues, HoveredLegend, ChartPane, SplitSeries, SingleSeries, CreateSplitSeriesParameters } from "./types/self" - * @import {createChart as CreateClassicChart, createChartEx as CreateCustomChart, LineStyleOptions} from "../packages/lightweight-charts/v4.2.0/types"; + * @import { Option, ResourceDataset, TimeScale, TimeRange, Unit, Weighted, DatasetPath, OHLC, FetchedJSON, DatasetValue, FetchedResult, AnyDatasetPath, Color, DatasetCandlestickData, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, AnyPath, SimulationOption, Frequency, LastValues } from "./types/self" + * @import {createChart as CreateClassicChart, createChartEx as CreateCustomChart, LineStyleOptions } from "../packages/lightweight-charts/v4.2.0/types"; + * @import { Marker, CreatePaneParameters, HoveredLegend, ChartPane, SplitSeries, SingleSeries, CreateSplitSeriesParameters, LineSeriesBlueprint, CandlestickSeriesBlueprint, BaselineSeriesBlueprint, CreateBaseSeriesParameters, BaseSeries, RemoveSeriesBlueprintFluff, SplitSeriesBlueprint } from "../packages/lightweight-charts/types"; * @import * as _ from "../packages/ufuzzy/v1.0.14/types" * @import { DeepPartial, ChartOptions, IChartApi, IHorzScaleBehavior, WhitespaceData, SingleValueData, ISeriesApi, Time, LineData, LogicalRange, SeriesMarker, CandlestickData, SeriesType, BaselineStyleOptions, SeriesOptionsCommon } from "../packages/lightweight-charts/v4.2.0/types" * @import { DatePath, HeightPath, LastPath } from "./types/paths"; @@ -232,6 +233,7 @@ const utils = { * @param {string} args.inputValue * @param {boolean} [args.inputChecked=false] * @param {string} args.labelTitle + * @param {'solo' | 'multi'} args.type * @param {(event: MouseEvent) => void} [args.onClick] */ createLabeledInput({ @@ -241,23 +243,27 @@ const utils = { inputChecked = false, labelTitle, onClick, + type, }) { const label = window.document.createElement("label"); inputId = inputId.toLowerCase(); const input = window.document.createElement("input"); - input.type = "radio"; - input.name = inputName; + if (type === "multi") { + input.type = "radio"; + input.name = inputName; + } else { + input.type = "checkbox"; + } input.id = inputId; input.value = inputValue; input.checked = inputChecked; label.append(input); label.id = `${inputId}-label`; - // @ts-ignore - label.for = inputId; label.title = labelTitle; + label.htmlFor = inputId; if (onClick) { label.addEventListener("click", onClick); @@ -362,6 +368,7 @@ const utils = { inputValue, inputChecked: inputValue === selected, labelTitle: choice, + type: "multi", }); const text = window.document.createTextNode(choice); @@ -835,6 +842,26 @@ const utils = { return new Date(v); }, }, + boolean: { + /** + * @param {boolean} v + */ + serialize(v) { + return String(v); + }, + /** + * @param {string} v + */ + deserialize(v) { + if (v === "true") { + return true; + } else if (v === "false") { + return false; + } else { + throw "deser bool err"; + } + }, + }, }, formatters: { dollars: new Intl.NumberFormat("en-US", { diff --git a/website/scripts/options.js b/website/scripts/options.js index ca9d591eb..983f05e97 100644 --- a/website/scripts/options.js +++ b/website/scripts/options.js @@ -1,7 +1,8 @@ // @ts-check /** - * @import { AnySpecificSeriesBlueprint, CohortOption, CohortOptions, Color, DefaultCohortOption, DefaultCohortOptions, OptionPath, OptionsGroup, PartialChartOption, PartialOptionsGroup, PartialOptionsTree, RatioOption, RatioOptions, SplitSeries, SeriesBlueprint, SeriesBlueprintParam, SeriesBluePrintType, TimeScale } from "./types/self" + * @import { CohortOption, CohortOptions, Color, DefaultCohortOption, DefaultCohortOptions, OptionPath, OptionsGroup, PartialChartOption, PartialOptionsGroup, PartialOptionsTree, RatioOption, RatioOptions, TimeScale } from "./types/self" + * @import {AnySpecificSeriesBlueprint, SplitSeriesBlueprint} from '../packages/lightweight-charts/types'; */ const DATE_TO_PREFIX = "date-to-"; @@ -2819,12 +2820,12 @@ function createPartialOptions(colors) { /** * @template {AnyPossibleCohortId} T * @param {CohortOption | CohortOptions} arg - * @param {SeriesBlueprintParam & Omit} blueprint + * @param {{ title: string; singleColor?: Color; genPath: (id: T, scale: TimeScale) => AnyDatasetPath} & Omit} blueprint */ - toSeriesBlueprints(arg, blueprint) { + generateSeriesBlueprints(arg, blueprint) { return this.toList(arg).map( ({ scale, datasetId, color, name }) => - /** @satisfies {SeriesBlueprint} */ ({ + /** @satisfies {SplitSeriesBlueprint} */ ({ title: cohortOptionOrOptions.toLegendName( arg, name, @@ -2886,7 +2887,7 @@ function createPartialOptions(colors) { title: `Number Of ${title} Unspent Transaction Outputs`, description: "", unit: "Count", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Count", genPath: (id, scale) => /** @type {const} */ ( @@ -2932,7 +2933,7 @@ function createPartialOptions(colors) { title: `${title} Realized Price`, description: "", unit: "US Dollars", - top: cohortOptionOrOptions.toSeriesBlueprints(arg, { + top: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Realized Price", genPath: (id, scale) => /** @type {const} */ ( @@ -2955,7 +2956,7 @@ function createPartialOptions(colors) { description: "", unit: "US Dollars", bottom: [ - ...cohortOptionOrOptions.toSeriesBlueprints( + ...cohortOptionOrOptions.generateSeriesBlueprints( arg, { @@ -2985,7 +2986,7 @@ function createPartialOptions(colors) { description: "", unit: "US Dollars", bottom: [ - ...cohortOptionOrOptions.toSeriesBlueprints( + ...cohortOptionOrOptions.generateSeriesBlueprints( arg, { @@ -3006,7 +3007,7 @@ function createPartialOptions(colors) { title: `${title} Realized Profit`, description: "", unit: "US Dollars", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Realized Profit", singleColor: colors.profit, genPath: (id, scale) => { @@ -3023,7 +3024,7 @@ function createPartialOptions(colors) { title: `${title} Realized Loss`, description: "", unit: "US Dollars", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Realized Loss", singleColor: colors.loss, genPath: (id, scale) => { @@ -3071,7 +3072,7 @@ function createPartialOptions(colors) { description: "", unit: "US Dollars", bottom: [ - ...cohortOptionOrOptions.toSeriesBlueprints(arg, { + ...cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Net PNL", type: "Baseline", genPath: (id, scale) => { @@ -3092,7 +3093,7 @@ function createPartialOptions(colors) { description: "", unit: "Percentage", bottom: [ - ...cohortOptionOrOptions.toSeriesBlueprints(arg, { + ...cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Net", type: "Baseline", genPath: (id) => @@ -3113,7 +3114,7 @@ function createPartialOptions(colors) { title: `${title} Cumulative Realized Profit`, description: "", unit: "US Dollars", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Cumulative Realized Profit", singleColor: colors.profit, genPath: (id, scale) => @@ -3128,7 +3129,7 @@ function createPartialOptions(colors) { title: `${title} Cumulative Realized Loss`, description: "", unit: "US Dollars", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Cumulative Realized Loss", singleColor: colors.loss, genPath: (id, scale) => @@ -3144,7 +3145,7 @@ function createPartialOptions(colors) { description: "", unit: "US Dollars", bottom: [ - ...cohortOptionOrOptions.toSeriesBlueprints(arg, { + ...cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Cumulative Net Realized PNL", type: "Baseline", genPath: (id, scale) => @@ -3162,7 +3163,7 @@ function createPartialOptions(colors) { description: "", unit: "US Dollars", bottom: [ - ...cohortOptionOrOptions.toSeriesBlueprints(arg, { + ...cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Cumulative Net Realized PNL 30d Change", type: "Baseline", genPath: (id, scale) => @@ -3182,7 +3183,7 @@ function createPartialOptions(colors) { description: "", unit: "Ratio", bottom: [ - ...cohortOptionOrOptions.toSeriesBlueprints(arg, { + ...cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Ratio", type: "Baseline", options: { @@ -3210,7 +3211,7 @@ function createPartialOptions(colors) { description: "", unit: "Percentage", bottom: [ - ...cohortOptionOrOptions.toSeriesBlueprints(arg, { + ...cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "SOPR", type: "Baseline", options: { @@ -3233,7 +3234,7 @@ function createPartialOptions(colors) { description: "", unit: "Percentage", bottom: [ - ...cohortOptionOrOptions.toSeriesBlueprints(arg, { + ...cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "aSOPR", type: "Baseline", options: { @@ -3263,7 +3264,7 @@ function createPartialOptions(colors) { title: `${title} Value Created`, description: "", unit: "US Dollars", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Value", singleColor: colors.profit, genPath: (id, scale) => { @@ -3280,7 +3281,7 @@ function createPartialOptions(colors) { title: `${title} Adjusted Value Created`, description: "", unit: "US Dollars", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Adjusted Value", singleColor: colors.profit, genPath: (id, scale) => { @@ -3302,7 +3303,7 @@ function createPartialOptions(colors) { title: `${title} Value Destroyed`, description: "", unit: "US Dollars", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Value", singleColor: colors.loss, genPath: (id, scale) => { @@ -3319,7 +3320,7 @@ function createPartialOptions(colors) { title: `${title} Adjusted Value Destroyed`, description: "", unit: "US Dollars", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Adjusted Value", singleColor: colors.loss, genPath: (id, scale) => { @@ -3341,7 +3342,7 @@ function createPartialOptions(colors) { title: `${title} Sell Side Risk Ratio`, description: "", unit: "Percentage", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Ratio", genPath: (id) => `${scale}-to-${datasetIdToPrefix(id)}sell-side-risk-ratio`, @@ -3368,7 +3369,7 @@ function createPartialOptions(colors) { title: `${title} Unrealized Profit`, description: "", unit: "US Dollars", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Profit", genPath: (id) => `${scale}-to-${datasetIdToPrefix(id)}unrealized-profit`, @@ -3381,7 +3382,7 @@ function createPartialOptions(colors) { title: `${title} Unrealized Loss`, description: "", unit: "US Dollars", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Loss", genPath: (id) => `${scale}-to-${datasetIdToPrefix(id)}unrealized-loss`, @@ -3419,7 +3420,7 @@ function createPartialOptions(colors) { description: "", unit: "US Dollars", bottom: [ - ...cohortOptionOrOptions.toSeriesBlueprints(arg, { + ...cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Net Unrealized PNL", genPath: (id) => `${scale}-to-${datasetIdToPrefix( @@ -3437,7 +3438,7 @@ function createPartialOptions(colors) { description: "", unit: "Percentage", bottom: [ - ...cohortOptionOrOptions.toSeriesBlueprints(arg, { + ...cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Relative Net Unrealized PNL", genPath: (id) => `${scale}-to-${datasetIdToPrefix( @@ -3505,7 +3506,7 @@ function createPartialOptions(colors) { title: `${title} Total supply`, description: "", unit: "Bitcoin", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Supply", genPath: (id) => `${scale}-to-${datasetIdToPrefix(id)}supply`, }), @@ -3516,7 +3517,7 @@ function createPartialOptions(colors) { title: `${title} Supply In Profit`, description: "", unit: "Bitcoin", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Supply", singleColor: colors.profit, genPath: (id) => @@ -3529,7 +3530,7 @@ function createPartialOptions(colors) { title: `${title} Supply In Loss`, description: "", unit: "Bitcoin", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Supply", singleColor: colors.loss, genPath: (id) => @@ -3581,7 +3582,7 @@ function createPartialOptions(colors) { title: `${title} Total supply Relative To Circulating Supply`, description: "", unit: "Percentage", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Supply", genPath: (id) => `${scale}-to-${datasetIdToPrefix( @@ -3595,7 +3596,7 @@ function createPartialOptions(colors) { title: `${title} Supply In Profit Relative To Circulating Supply`, description: "", unit: "Percentage", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Supply", singleColor: colors.profit, genPath: (id) => @@ -3610,7 +3611,7 @@ function createPartialOptions(colors) { title: `${title} Supply In Loss Relative To Circulating Supply`, description: "", unit: "Percentage", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Supply", singleColor: colors.loss, genPath: (id) => @@ -3668,7 +3669,7 @@ function createPartialOptions(colors) { title: `${title} Supply In Profit Relative To Own Supply`, description: "", unit: "Percentage", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Supply", singleColor: colors.profit, genPath: (id) => @@ -3683,7 +3684,7 @@ function createPartialOptions(colors) { title: `${title} Supply In Loss Relative To Own Supply`, description: "", unit: "Percentage", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Supply", singleColor: colors.loss, genPath: (id) => @@ -3732,7 +3733,7 @@ function createPartialOptions(colors) { title: `${title} Average Price Paid - Realized Price`, description: "", unit: "US Dollars", - top: cohortOptionOrOptions.toSeriesBlueprints(arg, { + top: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Average", genPath: (id) => `${scale}-to-${datasetIdToPrefix(id)}realized-price`, @@ -3768,7 +3769,7 @@ function createPartialOptions(colors) { title: `${title} ${percentile.title}`, description: "", unit: /** @type {const} */ ("US Dollars"), - top: cohortOptionOrOptions.toSeriesBlueprints(arg, { + top: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Relative Net Unrealized PNL", genPath: (id) => generatePath({ @@ -3923,7 +3924,7 @@ function createPartialOptions(colors) { title: `${title} Address Count`, description: "", unit: "Count", - bottom: cohortOptionOrOptions.toSeriesBlueprints(arg, { + bottom: cohortOptionOrOptions.generateSeriesBlueprints(arg, { title: "Address Count", genPath: (id) => `${scale}-to-${id}-address-count`, }), @@ -5199,7 +5200,7 @@ export function initOptions({ const optionsIds = env.localhost ? [] : undefined; /** - * @param {SeriesBlueprint[]} array + * @param {SplitSeriesBlueprint[]} array */ function getMainIdFromBlueprints(array) { const searchArray = array.filter( @@ -5316,6 +5317,7 @@ export function initOptions({ onClick: () => { selected.set(option); }, + type: "multi", }); const anchor = utils.dom.createAnchorElement({ diff --git a/website/scripts/simulation.js b/website/scripts/simulation.js index 311b130da..189820a39 100644 --- a/website/scripts/simulation.js +++ b/website/scripts/simulation.js @@ -33,15 +33,15 @@ export function init({ const frequencies = computeFrequencies(); - const storagePrefix = "save-in-bitcoin"; + const keyPrefix = "save-in-bitcoin"; const settings = { dollars: { initial: { amount: signals.createSignal(/** @type {number | null} */ (1000), { save: { ...utils.serde.number, - id: `${storagePrefix}-initial-amount`, - param: "initial-amount", + keyPrefix, + key: "initial-amount", }, }), }, @@ -49,8 +49,8 @@ export function init({ amount: signals.createSignal(/** @type {number | null} */ (150), { save: { ...utils.serde.number, - id: `${storagePrefix}-top-up-amount`, - param: "top-up-amount", + keyPrefix, + key: "top-up-amount", }, }), frenquency: signals.createSignal( @@ -58,8 +58,8 @@ export function init({ { save: { ...frequencies.serde, - id: `${storagePrefix}-top-up-freq`, - param: "top-up-freq", + keyPrefix, + key: "top-up-freq", }, }, ), @@ -70,15 +70,15 @@ export function init({ initial: signals.createSignal(/** @type {number | null} */ (1000), { save: { ...utils.serde.number, - id: `${storagePrefix}-initial-swap`, - param: "initial-swap", + keyPrefix, + key: "initial-swap", }, }), recurrent: signals.createSignal(/** @type {number | null} */ (5), { save: { ...utils.serde.number, - id: `${storagePrefix}-recurrent-swap`, - param: "recurrent-swap", + keyPrefix, + key: "recurrent-swap", }, }), frequency: signals.createSignal( @@ -86,8 +86,8 @@ export function init({ { save: { ...frequencies.serde, - id: `${storagePrefix}-swap-freq`, - param: "swap-freq", + keyPrefix, + key: "swap-freq", }, }, ), @@ -99,16 +99,16 @@ export function init({ { save: { ...utils.serde.date, - id: `${storagePrefix}-interval-start`, - param: "interval-start", + keyPrefix, + key: "interval-start", }, }, ), end: signals.createSignal(/** @type {Date | null} */ (new Date()), { save: { ...utils.serde.date, - id: `${storagePrefix}-interval-end`, - param: "interval-end", + keyPrefix, + key: "interval-end", }, }), }, @@ -116,8 +116,8 @@ export function init({ percentage: signals.createSignal(/** @type {number | null} */ (0.25), { save: { ...utils.serde.number, - id: `${storagePrefix}-percentage`, - param: "percentage", + keyPrefix, + key: "percentage", }, }), }, @@ -652,32 +652,28 @@ export function init({ unit: "US Dollars", config: [ { - title: "Bitcoin Value", - kind: "line", - color: colors.amber, - owner, - data: bitcoinValueData, + title: "Fees Paid", + type: "Line", + color: colors.rose, + data: () => totalFeesPaidData, }, { title: "Dollars Left", - kind: "line", + type: "Line", color: colors.offDollars, - owner, - data: dollarsLeftData, + data: () => dollarsLeftData, }, { title: "Dollars Converted", - kind: "line", + type: "Line", color: colors.dollars, - owner, - data: totalInvestedAmountData, + data: () => totalInvestedAmountData, }, { - title: "Fees Paid", - kind: "line", - color: colors.rose, - owner, - data: totalFeesPaidData, + title: "Bitcoin Value", + type: "Line", + color: colors.amber, + data: () => bitcoinValueData, }, ], }, @@ -698,10 +694,9 @@ export function init({ config: [ { title: "Bitcoin Stack", - kind: "line", + type: "Line", color: colors.bitcoin, - owner, - data: bitcoinData, + data: () => bitcoinData, }, ], }, @@ -722,17 +717,15 @@ export function init({ config: [ { title: "Bitcoin Price", - kind: "line", - owner, + type: "Line", color: colors.default, - data: bitcoinPriceData, + data: () => bitcoinPriceData, }, { title: "Average Price Paid", - kind: "line", - owner, + type: "Line", color: colors.lightDollars, - data: averagePricePaidData, + data: () => averagePricePaidData, }, ], }, @@ -753,9 +746,8 @@ export function init({ config: [ { title: "Return Of Investment", - kind: "baseline", - owner, - data: resultData, + type: "Baseline", + data: () => resultData, // TODO: Doesn't work for some reason // options: { // baseLineColor: "#888", @@ -780,23 +772,22 @@ export function init({ kind: "static", scale: "date", utils, + owner, config: [ { unit: "Percentage", config: [ { title: "Unprofitable Days Ratio", - kind: "line", - owner, + type: "Line", color: colors.red, - data: unprofitableDaysRatioData, + data: () => unprofitableDaysRatioData, }, { title: "Profitable Days Ratio", - kind: "line", - owner, + type: "Line", color: colors.green, - data: profitableDaysRatioData, + data: () => profitableDaysRatioData, }, ], }, @@ -818,8 +809,7 @@ function createInputField({ name, input }) { const label = window.document.createElement("label"); div.append(label); - // @ts-ignore - label.for = input.id; + label.htmlFor = input.id; label.innerHTML = name; div.append(input); @@ -856,8 +846,7 @@ function createFieldElement({ title, description, input }) { throw `Input should've an ID`; } - // @ts-ignore - label.for = forId; + label.htmlFor = forId; return div; } diff --git a/website/scripts/types/self.d.ts b/website/scripts/types/self.d.ts index 8443c7f24..2c33d27a6 100644 --- a/website/scripts/types/self.d.ts +++ b/website/scripts/types/self.d.ts @@ -17,7 +17,6 @@ import { BaselineData, } from "../../packages/lightweight-charts/v4.2.0/types"; import { DatePath, HeightPath, LastPath } from "./paths"; -import { Owner } from "../../packages/solid-signals/2024-11-02/types/core/owner"; import { AnyPossibleCohortId } from "../options"; import { Signal } from "../../packages/solid-signals/types"; @@ -42,53 +41,6 @@ type AnyPath = AnyDatasetPath | LastPath; type Color = () => string; type ColorName = keyof Colors; -interface BaselineSpecificSeriesBlueprint { - type: "Baseline"; - color?: Color; - options?: DeepPartial; - data?: BaselineData