mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-29 17:19:57 -07:00
general: snapshot
This commit is contained in:
@@ -1,28 +0,0 @@
|
||||
import { defaultSeriesOptions } from "./options";
|
||||
|
||||
type AreaOptions = DeepPartial<AreaStyleOptions & SeriesOptionsCommon>;
|
||||
|
||||
export const createAreaSeries = (
|
||||
chart: IChartApi,
|
||||
options?: AreaOptions & {
|
||||
color?: string;
|
||||
},
|
||||
) => {
|
||||
const { color } = options || {};
|
||||
|
||||
// const fillColor = `${color}11`;
|
||||
const fillColor = color;
|
||||
|
||||
const seriesOptions: AreaOptions = {
|
||||
// priceScaleId: 'left',
|
||||
...defaultSeriesOptions,
|
||||
lineColor: color,
|
||||
topColor: fillColor,
|
||||
bottomColor: fillColor,
|
||||
...options,
|
||||
};
|
||||
|
||||
const series = chart.addAreaSeries(seriesOptions);
|
||||
|
||||
return series;
|
||||
};
|
||||
@@ -10,43 +10,51 @@ export const DEFAULT_BASELINE_COLORS = [
|
||||
DEFAULT_BASELINE_BOTTOM_COLOR,
|
||||
];
|
||||
|
||||
export const createBaseLineSeries = (
|
||||
chart: IChartApi,
|
||||
options: BaselineSeriesOptions,
|
||||
) => {
|
||||
const {
|
||||
title,
|
||||
color,
|
||||
topColor,
|
||||
topLineColor,
|
||||
bottomColor,
|
||||
bottomLineColor,
|
||||
base,
|
||||
lineColor,
|
||||
} = options;
|
||||
const transparent = `transparent`;
|
||||
|
||||
const allTopColor = topColor || color || DEFAULT_BASELINE_TOP_COLOR;
|
||||
const topFillColor = `transparent`;
|
||||
const allBottomColor = bottomColor || color || DEFAULT_BASELINE_BOTTOM_COLOR;
|
||||
const bottomFillColor = `transparent`;
|
||||
export const createBaseLineSeries = ({
|
||||
chart,
|
||||
dark,
|
||||
color,
|
||||
topColor,
|
||||
bottomColor,
|
||||
options,
|
||||
}: {
|
||||
chart: IChartApi;
|
||||
dark: Accessor<boolean>;
|
||||
color?: Color;
|
||||
topColor?: Color;
|
||||
bottomColor?: Color;
|
||||
options?: DeepPartialBaselineOptions & {
|
||||
base?: number;
|
||||
};
|
||||
}) => {
|
||||
const topLineColor = topColor || color || DEFAULT_BASELINE_TOP_COLOR;
|
||||
|
||||
const bottomLineColor = bottomColor || color || DEFAULT_BASELINE_BOTTOM_COLOR;
|
||||
|
||||
const seriesOptions: DeepPartialBaselineOptions = {
|
||||
priceScaleId: "right",
|
||||
...defaultSeriesOptions,
|
||||
// lineWidth: 1,
|
||||
...options,
|
||||
...options.options,
|
||||
...(base ? { baseValue: { type: "price", price: base } } : {}),
|
||||
topLineColor: topLineColor || lineColor || allTopColor,
|
||||
topFillColor1: topFillColor,
|
||||
topFillColor2: topFillColor,
|
||||
bottomLineColor: bottomLineColor || lineColor || allBottomColor,
|
||||
bottomFillColor1: bottomFillColor,
|
||||
bottomFillColor2: bottomFillColor,
|
||||
title,
|
||||
...(options?.base
|
||||
? { baseValue: { type: "price", price: options?.base } }
|
||||
: {}),
|
||||
topFillColor1: transparent,
|
||||
topFillColor2: transparent,
|
||||
bottomFillColor1: transparent,
|
||||
bottomFillColor2: transparent,
|
||||
};
|
||||
|
||||
const series = chart.addBaselineSeries(seriesOptions);
|
||||
|
||||
createEffect(() => {
|
||||
series.applyOptions({
|
||||
topLineColor: topLineColor(dark),
|
||||
bottomLineColor: bottomLineColor(dark),
|
||||
});
|
||||
});
|
||||
|
||||
return series;
|
||||
};
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
import { colors } from "/src/scripts/utils/colors";
|
||||
|
||||
export const createCandlesticksSeries = (
|
||||
chart: IChartApi,
|
||||
options: PriceSeriesOptions = {},
|
||||
): [ISeriesApi<"Candlestick">, string[]] => {
|
||||
export const createCandlesticksSeries = ({
|
||||
chart,
|
||||
dark,
|
||||
options = {},
|
||||
}: {
|
||||
chart: IChartApi;
|
||||
dark: Accessor<boolean>;
|
||||
options?: PriceSeriesOptions;
|
||||
}): [ISeriesApi<"Candlestick">, Color[]] => {
|
||||
const { inverseColors } = options;
|
||||
|
||||
const upColor = inverseColors ? colors.loss : colors.profit;
|
||||
|
||||
const downColor = inverseColors ? colors.profit : colors.loss;
|
||||
|
||||
const candlestickSeries = chart.addCandlestickSeries({
|
||||
baseLineVisible: false,
|
||||
upColor,
|
||||
wickUpColor: upColor,
|
||||
downColor,
|
||||
wickDownColor: downColor,
|
||||
borderVisible: false,
|
||||
priceLineVisible: false,
|
||||
baseLineColor: "",
|
||||
@@ -25,5 +22,22 @@ export const createCandlesticksSeries = (
|
||||
...options.seriesOptions,
|
||||
});
|
||||
|
||||
return [candlestickSeries, [upColor, downColor]];
|
||||
const _upColor = inverseColors ? colors.loss : colors.profit;
|
||||
|
||||
const _downColor = inverseColors ? colors.profit : colors.loss;
|
||||
|
||||
createEffect(() => {
|
||||
const upColor = _upColor(dark);
|
||||
|
||||
const downColor = _downColor(dark);
|
||||
|
||||
candlestickSeries.applyOptions({
|
||||
upColor,
|
||||
wickUpColor: upColor,
|
||||
downColor,
|
||||
wickDownColor: downColor,
|
||||
});
|
||||
});
|
||||
|
||||
return [candlestickSeries, [_upColor, _downColor]];
|
||||
};
|
||||
|
||||
@@ -15,34 +15,24 @@ export function createChart(
|
||||
dark,
|
||||
priceScaleOptions,
|
||||
}: {
|
||||
dark: boolean;
|
||||
dark: Accessor<boolean>;
|
||||
priceScaleOptions: DeepPartialPriceScaleOptions;
|
||||
},
|
||||
) {
|
||||
console.log(`chart: create (scale: ${scale})`);
|
||||
|
||||
const { white, black } = colors;
|
||||
|
||||
const textColor = dark ? white : black;
|
||||
const borderColor = dark ? "#332F24" : "#F1E4E0";
|
||||
|
||||
const options: DeepPartialChartOptions = {
|
||||
autoSize: true,
|
||||
layout: {
|
||||
fontFamily: "Lexend",
|
||||
background: { color: "transparent" },
|
||||
fontSize: 14,
|
||||
textColor,
|
||||
},
|
||||
grid: {
|
||||
vertLines: { visible: false },
|
||||
horzLines: { visible: false },
|
||||
},
|
||||
rightPriceScale: {
|
||||
borderColor,
|
||||
},
|
||||
timeScale: {
|
||||
borderColor,
|
||||
minBarSpacing: 0.05,
|
||||
shiftVisibleRangeOnNewBar: false,
|
||||
allowShiftVisibleRangeOnWhitespaceReplacement: false,
|
||||
@@ -54,14 +44,6 @@ export function createChart(
|
||||
},
|
||||
crosshair: {
|
||||
mode: CrosshairMode.Normal,
|
||||
horzLine: {
|
||||
color: textColor,
|
||||
labelBackgroundColor: textColor,
|
||||
},
|
||||
vertLine: {
|
||||
color: textColor,
|
||||
labelBackgroundColor: textColor,
|
||||
},
|
||||
},
|
||||
localization: {
|
||||
priceFormatter: valueToString,
|
||||
@@ -90,5 +72,34 @@ export function createChart(
|
||||
minimumWidth: 78,
|
||||
});
|
||||
|
||||
createEffect(() => {
|
||||
const { white } = colors;
|
||||
|
||||
const textColor = white(dark);
|
||||
const borderColor = dark() ? "#332F24" : "#F1E4E0";
|
||||
|
||||
chart.applyOptions({
|
||||
layout: {
|
||||
textColor,
|
||||
},
|
||||
rightPriceScale: {
|
||||
borderColor,
|
||||
},
|
||||
timeScale: {
|
||||
borderColor,
|
||||
},
|
||||
crosshair: {
|
||||
horzLine: {
|
||||
color: textColor,
|
||||
labelBackgroundColor: textColor,
|
||||
},
|
||||
vertLine: {
|
||||
color: textColor,
|
||||
labelBackgroundColor: textColor,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
return chart;
|
||||
}
|
||||
|
||||
@@ -6,10 +6,17 @@ type HistogramOptions = DeepPartial<
|
||||
|
||||
export const PRICE_SCALE_MOMENTUM_ID = "momentum";
|
||||
|
||||
export const createHistogramSeries = (
|
||||
chart: IChartApi,
|
||||
options?: HistogramOptions,
|
||||
) => {
|
||||
export const createHistogramSeries = ({
|
||||
chart,
|
||||
// dark,
|
||||
// color,
|
||||
options,
|
||||
}: {
|
||||
chart: IChartApi;
|
||||
// dark: Accessor<boolean>;
|
||||
// color: Color;
|
||||
options?: HistogramOptions;
|
||||
}) => {
|
||||
const seriesOptions: HistogramOptions = {
|
||||
priceScaleId: "left",
|
||||
...defaultSeriesOptions,
|
||||
|
||||
@@ -9,6 +9,7 @@ export class HorzScaleBehaviorHeight implements IHorzScaleBehavior<number> {
|
||||
setOptions() {}
|
||||
preprocessData() {}
|
||||
updateFormatter() {}
|
||||
|
||||
createConverterToInternalObj() {
|
||||
return (price) => price;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ export function createSeriesLegend<Scale extends ResourceScale>({
|
||||
id: string;
|
||||
presetId: string;
|
||||
title: string;
|
||||
color: Accessor<string | string[]>;
|
||||
color: Color | Color[];
|
||||
seriesList: Accessor<ISeriesApi<SeriesType> | undefined>[];
|
||||
defaultVisible?: boolean;
|
||||
disabled?: Accessor<boolean>;
|
||||
|
||||
@@ -1,10 +1,26 @@
|
||||
import { defaultSeriesOptions } from "./options";
|
||||
|
||||
export const createLineSeries = (
|
||||
chart: IChartApi,
|
||||
options?: DeepPartialLineOptions,
|
||||
) =>
|
||||
chart.addLineSeries({
|
||||
export const createLineSeries = ({
|
||||
chart,
|
||||
dark,
|
||||
color,
|
||||
options,
|
||||
}: {
|
||||
chart: IChartApi;
|
||||
dark: Accessor<boolean>;
|
||||
color: Color;
|
||||
options?: DeepPartialLineOptions;
|
||||
}) => {
|
||||
const series = chart.addLineSeries({
|
||||
...defaultSeriesOptions,
|
||||
...options,
|
||||
});
|
||||
|
||||
createEffect(() => {
|
||||
series.applyOptions({
|
||||
color: color(dark),
|
||||
});
|
||||
});
|
||||
|
||||
return series;
|
||||
};
|
||||
|
||||
@@ -6,12 +6,12 @@ export function setMinMaxMarkers({
|
||||
scale,
|
||||
visibleRange,
|
||||
legendList,
|
||||
activeRange,
|
||||
activeIds,
|
||||
}: {
|
||||
scale: ResourceScale;
|
||||
visibleRange: TimeRange | undefined;
|
||||
legendList: SeriesLegend[];
|
||||
activeRange: Accessor<number[]>;
|
||||
activeIds: Accessor<number[]>;
|
||||
}) {
|
||||
if (!visibleRange) return;
|
||||
|
||||
@@ -24,7 +24,7 @@ export function setMinMaxMarkers({
|
||||
let min = undefined as [number, Time, number, ISeriesApi<any>] | undefined;
|
||||
|
||||
legendList.forEach(({ seriesList, dataset }) => {
|
||||
activeRange().forEach((id) => {
|
||||
activeIds().forEach((id) => {
|
||||
const seriesIndex = chunkIdToIndex(scale, id);
|
||||
|
||||
const series = seriesList.at(seriesIndex)?.();
|
||||
|
||||
@@ -1,48 +1,13 @@
|
||||
import { HEIGHT_CHUNK_SIZE } from "../datasets";
|
||||
import { debounce } from "../utils/debounce";
|
||||
import { tick } from "../utils/tick";
|
||||
import { writeURLParam } from "../utils/urlParams";
|
||||
|
||||
const LOCAL_STORAGE_RANGE_KEY = "chart-range";
|
||||
const URL_PARAMS_RANGE_FROM_KEY = "from";
|
||||
const URL_PARAMS_RANGE_TO_KEY = "to";
|
||||
|
||||
export function initTimeScale({
|
||||
scale,
|
||||
activeRange,
|
||||
exactRange,
|
||||
charts,
|
||||
}: {
|
||||
scale: ResourceScale;
|
||||
activeRange: RWS<number[]>;
|
||||
exactRange: RWS<TimeRange | undefined>;
|
||||
charts: ChartObject[];
|
||||
}) {
|
||||
const firstChart = charts.at(0)?.chart;
|
||||
|
||||
if (!firstChart) return;
|
||||
|
||||
firstChart.timeScale().subscribeVisibleTimeRangeChange((range) => {
|
||||
if (!range) return;
|
||||
|
||||
exactRange.set(range);
|
||||
|
||||
debouncedSetActiveRange({ range, activeRange });
|
||||
|
||||
debouncedSaveTimeRange({ scale, range });
|
||||
});
|
||||
|
||||
setTimeScale(firstChart, getInitialRange(scale));
|
||||
}
|
||||
|
||||
function setTimeScale(chart: IChartApi, range: TimeRange | null) {
|
||||
if (range) {
|
||||
setTimeout(() => {
|
||||
chart.timeScale().setVisibleRange(range);
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
|
||||
function getInitialRange(scale: ResourceScale): TimeRange {
|
||||
export function getInitialTimeRange(scale: ResourceScale): TimeRange {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
|
||||
const urlFrom = urlParams.get(URL_PARAMS_RANGE_FROM_KEY);
|
||||
@@ -94,38 +59,76 @@ function getInitialRange(scale: ResourceScale): TimeRange {
|
||||
}
|
||||
}
|
||||
|
||||
export function initTimeScale({
|
||||
scale,
|
||||
activeIds,
|
||||
exactRange,
|
||||
charts,
|
||||
}: {
|
||||
scale: ResourceScale;
|
||||
activeIds: RWS<number[]>;
|
||||
exactRange: RWS<TimeRange>;
|
||||
charts: ChartObject[];
|
||||
}) {
|
||||
const firstChart = charts.at(0)?.chart;
|
||||
|
||||
if (!firstChart) return;
|
||||
|
||||
firstChart.timeScale().subscribeVisibleTimeRangeChange((range) => {
|
||||
if (!range) return;
|
||||
|
||||
exactRange.set(range);
|
||||
|
||||
debouncedsetActiveIds({ exactRange: range, activeIds: activeIds });
|
||||
|
||||
debouncedSaveTimeRange({ scale, range });
|
||||
});
|
||||
|
||||
setTimeScale(firstChart, exactRange());
|
||||
}
|
||||
|
||||
async function setTimeScale(chart: IChartApi, range: TimeRange | null) {
|
||||
if (range) {
|
||||
await tick();
|
||||
chart.timeScale().setVisibleRange(range);
|
||||
}
|
||||
}
|
||||
|
||||
function getLocalStorageKey(scale: ResourceScale) {
|
||||
return `${LOCAL_STORAGE_RANGE_KEY}-${scale}`;
|
||||
}
|
||||
|
||||
function setActiveRange({
|
||||
range,
|
||||
activeRange,
|
||||
export function setActiveIds({
|
||||
exactRange,
|
||||
activeIds,
|
||||
}: {
|
||||
range: TimeRange;
|
||||
activeRange: RWS<number[]>;
|
||||
exactRange: TimeRange;
|
||||
activeIds: RWS<number[]>;
|
||||
}) {
|
||||
let ids: number[] = [];
|
||||
|
||||
const today = new Date();
|
||||
|
||||
if (typeof range.from === "string" && typeof range.to === "string") {
|
||||
const from = new Date(range.from).getUTCFullYear();
|
||||
const to = new Date(range.to).getUTCFullYear();
|
||||
if (
|
||||
typeof exactRange.from === "string" &&
|
||||
typeof exactRange.to === "string"
|
||||
) {
|
||||
const from = new Date(exactRange.from).getUTCFullYear();
|
||||
const to = new Date(exactRange.to).getUTCFullYear();
|
||||
|
||||
ids = Array.from({ length: to - from + 1 }, (_, i) => i + from).filter(
|
||||
(year) => year >= 2009 && year <= today.getUTCFullYear(),
|
||||
);
|
||||
} else {
|
||||
const from = Math.floor(Number(range.from) / HEIGHT_CHUNK_SIZE);
|
||||
const to = Math.floor(Number(range.to) / HEIGHT_CHUNK_SIZE);
|
||||
const from = Math.floor(Number(exactRange.from) / HEIGHT_CHUNK_SIZE);
|
||||
const to = Math.floor(Number(exactRange.to) / HEIGHT_CHUNK_SIZE);
|
||||
|
||||
const length = to - from + 1;
|
||||
|
||||
ids = Array.from({ length }, (_, i) => (from + i) * HEIGHT_CHUNK_SIZE);
|
||||
}
|
||||
|
||||
const old = activeRange();
|
||||
const old = activeIds();
|
||||
|
||||
if (
|
||||
old.length !== ids.length ||
|
||||
@@ -134,11 +137,11 @@ function setActiveRange({
|
||||
) {
|
||||
console.log("range:", ids);
|
||||
|
||||
activeRange.set(ids);
|
||||
activeIds.set(ids);
|
||||
}
|
||||
}
|
||||
|
||||
const debouncedSetActiveRange = debounce(setActiveRange, 100);
|
||||
const debouncedsetActiveIds = debounce(setActiveIds, 100);
|
||||
|
||||
function saveTimeRange({
|
||||
scale,
|
||||
|
||||
4
app/src/scripts/lightweightCharts/types.d.ts
vendored
4
app/src/scripts/lightweightCharts/types.d.ts
vendored
@@ -19,6 +19,4 @@ interface BaselineSeriesOptions {
|
||||
title?: string;
|
||||
}
|
||||
|
||||
type SeriesLegend = ReturnType<
|
||||
typeof import("../../chart/legend").createSeriesLegend
|
||||
>;
|
||||
type SeriesLegend = ReturnType<typeof import("./legend").createSeriesLegend>;
|
||||
|
||||
@@ -4,9 +4,9 @@ import { createLineSeries } from "./line";
|
||||
export const GENESIS_DAY = "2009-01-03";
|
||||
|
||||
const whitespaceStartDate = new Date("1970-01-01");
|
||||
const whitespaceStartDateYear = whitespaceStartDate.getFullYear();
|
||||
const whitespaceStartDateMonth = whitespaceStartDate.getMonth();
|
||||
const whitespaceStartDateDate = whitespaceStartDate.getDate();
|
||||
const whitespaceStartDateYear = whitespaceStartDate.getUTCFullYear();
|
||||
const whitespaceStartDateMonth = whitespaceStartDate.getUTCMonth();
|
||||
const whitespaceStartDateDate = whitespaceStartDate.getUTCDate();
|
||||
const whitespaceEndDate = new Date("2141-01-01");
|
||||
const whitespaceDateDataset: (WhitespaceData | SingleValueData)[] = new Array(
|
||||
getNumberOfDaysBetweenTwoDates(whitespaceStartDate, whitespaceEndDate),
|
||||
@@ -47,7 +47,7 @@ for (let i = 0; i < whitespaceHeightDataset.length; i++) {
|
||||
}
|
||||
|
||||
export function setWhitespace(chart: IChartApi, scale: ResourceScale) {
|
||||
const whitespace = createLineSeries(chart);
|
||||
const whitespace = chart.addLineSeries();
|
||||
|
||||
if (scale === "date") {
|
||||
whitespace.setData(whitespaceDateDataset);
|
||||
@@ -63,3 +63,81 @@ export function setWhitespace(chart: IChartApi, scale: ResourceScale) {
|
||||
|
||||
return whitespace;
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
// import { HEIGHT_CHUNK_SIZE } from "../datasets";
|
||||
// import { dateToString } from "../utils/date";
|
||||
|
||||
// export const GENESIS_DAY = "2009-01-03";
|
||||
|
||||
// function leapYear(year: number) {
|
||||
// return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
|
||||
// }
|
||||
|
||||
// const whitespaceStartDate = new Date("1970-01-01");
|
||||
// export const whitespaceStartDateYear = whitespaceStartDate.getFullYear();
|
||||
// const whitespaceStartDateMonth = whitespaceStartDate.getMonth();
|
||||
// const whitespaceStartDateDate = whitespaceStartDate.getDate();
|
||||
// const whitespaceEndDate = new Date("2141-01-01");
|
||||
// const whitespaceEndDateYear = whitespaceEndDate.getFullYear();
|
||||
|
||||
// export const whitespaceDateDatasets: (WhitespaceData | SingleValueData)[][] =
|
||||
// Array.from(
|
||||
// { length: whitespaceEndDateYear - whitespaceStartDateYear },
|
||||
// (_, i) => new Array(leapYear(whitespaceStartDateYear + i) ? 366 : 365),
|
||||
// );
|
||||
// for (let i = 0; i < whitespaceDateDatasets.length; i++) {
|
||||
// const year = whitespaceStartDateYear + i;
|
||||
// const whitespaceDateDataset = whitespaceDateDatasets[i];
|
||||
|
||||
// // Hack to be able to scroll freely
|
||||
// // Setting them all to NaN is much slower
|
||||
// for (let j = 0; j < whitespaceDateDataset.length; j++) {
|
||||
// const date = new Date(
|
||||
// year,
|
||||
// whitespaceStartDateMonth,
|
||||
// whitespaceStartDateDate + j,
|
||||
// );
|
||||
|
||||
// const time = dateToString(date);
|
||||
|
||||
// if (j === whitespaceDateDataset.length - 1) {
|
||||
// whitespaceDateDataset[j] = {
|
||||
// time,
|
||||
// value: NaN,
|
||||
// };
|
||||
// } else {
|
||||
// whitespaceDateDataset[j] = {
|
||||
// time,
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// export const whitespaceHeightStart = -50_000;
|
||||
// export const whitespaceHeightDatasets: (WhitespaceData | SingleValueData)[][] =
|
||||
// Array.from(
|
||||
// { length: (new Date().getUTCFullYear() - 2009 + 1) * 6 },
|
||||
// () => new Array(HEIGHT_CHUNK_SIZE),
|
||||
// );
|
||||
|
||||
// for (let i = 0; i < whitespaceHeightDatasets.length; i++) {
|
||||
// const offset = HEIGHT_CHUNK_SIZE * i;
|
||||
// const whitespaceHeightDataset = whitespaceHeightDatasets[i];
|
||||
|
||||
// for (let j = 0; j < whitespaceHeightDataset.length; j++) {
|
||||
// const height = whitespaceHeightStart + offset + j;
|
||||
|
||||
// if (j === whitespaceHeightDataset.length - 1) {
|
||||
// whitespaceHeightDataset[j] = {
|
||||
// time: height as any,
|
||||
// value: NaN,
|
||||
// };
|
||||
// } else {
|
||||
// whitespaceHeightDataset[j] = {
|
||||
// time: height as any,
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -127,7 +127,7 @@ function createAddressPresetFolder<Scale extends ResourceScale>({
|
||||
scale: Scale;
|
||||
name: string;
|
||||
datasetKey: AddressCohortKey;
|
||||
color: string;
|
||||
color: Color;
|
||||
}): PartialPresetFolder {
|
||||
return {
|
||||
name,
|
||||
@@ -159,7 +159,7 @@ export function createLiquidityFolder<Scale extends ResourceScale>({
|
||||
scale: Scale;
|
||||
name: string;
|
||||
datasetKey: AddressCohortKey | "";
|
||||
color: string;
|
||||
color: Color;
|
||||
}): PartialPresetFolder {
|
||||
return {
|
||||
name: `Split By Liquidity`,
|
||||
@@ -189,7 +189,7 @@ export function createAddressCountPreset<Scale extends ResourceScale>({
|
||||
scale: Scale;
|
||||
name: string;
|
||||
datasetKey: AddressCohortKey;
|
||||
color: string;
|
||||
color: Color;
|
||||
}): PartialPreset {
|
||||
return {
|
||||
scale,
|
||||
|
||||
@@ -11,7 +11,11 @@ import { createHistogramSeries } from "../lightweightCharts/histogram";
|
||||
import { createSeriesLegend } from "../lightweightCharts/legend";
|
||||
import { createLineSeries } from "../lightweightCharts/line";
|
||||
import { setMinMaxMarkers } from "../lightweightCharts/markers";
|
||||
import { initTimeScale } from "../lightweightCharts/time";
|
||||
import {
|
||||
getInitialTimeRange,
|
||||
initTimeScale,
|
||||
setActiveIds,
|
||||
} from "../lightweightCharts/time";
|
||||
import { setWhitespace } from "../lightweightCharts/whitespace";
|
||||
import { colors } from "../utils/colors";
|
||||
import { debounce } from "../utils/debounce";
|
||||
@@ -27,7 +31,9 @@ export enum SeriesType {
|
||||
type SeriesConfig<Scale extends ResourceScale> =
|
||||
| {
|
||||
dataset: ResourceDataset<Scale>;
|
||||
color?: string;
|
||||
color?: Color;
|
||||
topColor?: Color;
|
||||
bottomColor?: Color;
|
||||
colors?: undefined;
|
||||
seriesType: SeriesType.Based;
|
||||
title: string;
|
||||
@@ -37,8 +43,8 @@ type SeriesConfig<Scale extends ResourceScale> =
|
||||
}
|
||||
| {
|
||||
dataset: ResourceDataset<Scale>;
|
||||
color?: string;
|
||||
colors?: string[];
|
||||
color?: Color;
|
||||
colors?: Color[];
|
||||
seriesType: SeriesType.Histogram;
|
||||
title: string;
|
||||
options?: DeepPartialHistogramOptions;
|
||||
@@ -57,7 +63,7 @@ type SeriesConfig<Scale extends ResourceScale> =
|
||||
}
|
||||
| {
|
||||
dataset: ResourceDataset<Scale>;
|
||||
color: string;
|
||||
color: Color;
|
||||
colors?: undefined;
|
||||
seriesType?: SeriesType.Line;
|
||||
title: string;
|
||||
@@ -78,7 +84,7 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
priceOptions,
|
||||
legendSetter,
|
||||
dark,
|
||||
activeRange,
|
||||
activeIds,
|
||||
}: {
|
||||
charts: RWS<IChartApi[]>;
|
||||
parentDiv: HTMLDivElement;
|
||||
@@ -90,8 +96,8 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
top?: SeriesConfig<Scale>[];
|
||||
bottom?: SeriesConfig<Scale>[];
|
||||
datasets: Datasets;
|
||||
dark: boolean;
|
||||
activeRange: RWS<number[]>;
|
||||
dark: Accessor<boolean>;
|
||||
activeIds: RWS<number[]>;
|
||||
}) {
|
||||
// ---
|
||||
// Reset states
|
||||
@@ -107,8 +113,6 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
return [];
|
||||
});
|
||||
|
||||
activeRange.set([]);
|
||||
|
||||
parentDiv.replaceChildren();
|
||||
|
||||
// ---
|
||||
@@ -124,11 +128,18 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
const activeDatasets: ResourceDataset<any, any>[] = [];
|
||||
|
||||
const lastActiveIndex = createMemo(() => {
|
||||
const last = activeRange().at(-1);
|
||||
const last = activeIds().at(-1);
|
||||
return last !== undefined ? chunkIdToIndex(scale, last) : undefined;
|
||||
});
|
||||
|
||||
const exactRange = createRWS(undefined as TimeRange | undefined);
|
||||
const exactRange = createRWS(getInitialTimeRange(scale));
|
||||
|
||||
setActiveIds({
|
||||
exactRange: exactRange(),
|
||||
activeIds: activeIds,
|
||||
});
|
||||
|
||||
const seriesNumber = 1 + (top || []).length + (bottom || []).length;
|
||||
|
||||
const charts = [top || [], bottom]
|
||||
.flatMap((list) => (list ? [list] : []))
|
||||
@@ -157,16 +168,74 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
|
||||
const whitespace = setWhitespace(chart, scale);
|
||||
|
||||
if (exactRange()) {
|
||||
chart.timeScale().setVisibleRange(exactRange());
|
||||
}
|
||||
|
||||
// const whitespace = new Array<ISeriesApi<"Line"> | undefined>(
|
||||
// scale === "date"
|
||||
// ? whitespaceDateDatasets.length
|
||||
// : whitespaceHeightDatasets.length,
|
||||
// ).fill(undefined);
|
||||
|
||||
// function createWhitespaceSeriesIfNeeded(index: number) {
|
||||
// console.log(index);
|
||||
// if (index >= 0 && index < whitespace.length && !whitespace[index]) {
|
||||
// const series = createLineSeries(chart);
|
||||
// whitespace[index] = series;
|
||||
|
||||
// if (scale === "date") {
|
||||
// series.setData(whitespaceDateDatasets[index]);
|
||||
// } else {
|
||||
// series.setData(whitespaceHeightDatasets[index]);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// createEffect(() => {
|
||||
// const ids = activeIds();
|
||||
// console.log(ids);
|
||||
|
||||
// const idsLength = ids.length;
|
||||
// for (let i = 0; i < idsLength; i++) {
|
||||
// const id = ids[i];
|
||||
|
||||
// const whitespaceIndex = chunkIdToIndex(
|
||||
// scale,
|
||||
// scale === "date"
|
||||
// ? id - whitespaceStartDateYear
|
||||
// : id - whitespaceHeightStart,
|
||||
// );
|
||||
|
||||
// if (i === 0) {
|
||||
// createWhitespaceSeriesIfNeeded(whitespaceIndex - 1);
|
||||
// }
|
||||
|
||||
// createWhitespaceSeriesIfNeeded(whitespaceIndex);
|
||||
|
||||
// if (i === idsLength - 1) {
|
||||
// createWhitespaceSeriesIfNeeded(whitespaceIndex + 1);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
const chartLegend: SeriesLegend[] = [];
|
||||
|
||||
const debouncedSetMinMaxMarkers = debounce(() => {
|
||||
function _setMinMaxMarkers() {
|
||||
setMinMaxMarkers({
|
||||
scale,
|
||||
visibleRange: exactRange(),
|
||||
legendList: chartLegend,
|
||||
activeRange,
|
||||
activeIds: activeIds,
|
||||
});
|
||||
}, 50);
|
||||
}
|
||||
|
||||
const debouncedSetMinMaxMarkers = debounce(
|
||||
_setMinMaxMarkers,
|
||||
seriesNumber * 10,
|
||||
);
|
||||
|
||||
createEffect(on(exactRange, debouncedSetMinMaxMarkers));
|
||||
|
||||
if (index === 0) {
|
||||
const dataset =
|
||||
@@ -206,7 +275,7 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
}
|
||||
|
||||
return createSeriesGroup({
|
||||
activeRange,
|
||||
activeIds,
|
||||
seriesConfig,
|
||||
chart,
|
||||
chartLegend,
|
||||
@@ -214,6 +283,7 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
preset,
|
||||
disabled: () => priceSeriesType() !== seriesType,
|
||||
debouncedSetMinMaxMarkers,
|
||||
dark,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -233,13 +303,14 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
activeDatasets.push(seriesConfig.dataset);
|
||||
|
||||
createSeriesGroup({
|
||||
activeRange,
|
||||
activeIds: activeIds,
|
||||
seriesConfig,
|
||||
chartLegend,
|
||||
chart,
|
||||
preset,
|
||||
lastActiveIndex,
|
||||
debouncedSetMinMaxMarkers,
|
||||
dark,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -249,8 +320,6 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
createEffect(on(legend.visible, debouncedSetMinMaxMarkers));
|
||||
});
|
||||
|
||||
createEffect(on(exactRange, debouncedSetMinMaxMarkers));
|
||||
|
||||
return [
|
||||
{
|
||||
scale,
|
||||
@@ -271,7 +340,8 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
chart.div.style.border = "";
|
||||
visibleCharts.push(chart);
|
||||
} else {
|
||||
chart.div.style.height = "0px";
|
||||
chart.div.style.height = "100%";
|
||||
// chart.div.style.height = "0px";
|
||||
chart.div.style.border = "none";
|
||||
}
|
||||
});
|
||||
@@ -296,13 +366,13 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
initTimeScale({
|
||||
scale,
|
||||
charts,
|
||||
activeRange,
|
||||
activeIds: activeIds,
|
||||
exactRange,
|
||||
});
|
||||
|
||||
const activeDatasetsLength = activeDatasets.length;
|
||||
createEffect(() => {
|
||||
const range = activeRange();
|
||||
const range = activeIds();
|
||||
|
||||
untrack(() => {
|
||||
for (let i = 0; i < range.length; i++) {
|
||||
@@ -382,7 +452,7 @@ function updateVisiblePriceSeriesType(
|
||||
}
|
||||
|
||||
function createSeriesGroup<Scale extends ResourceScale>({
|
||||
activeRange,
|
||||
activeIds,
|
||||
seriesConfig,
|
||||
preset,
|
||||
chartLegend,
|
||||
@@ -390,8 +460,9 @@ function createSeriesGroup<Scale extends ResourceScale>({
|
||||
disabled,
|
||||
lastActiveIndex,
|
||||
debouncedSetMinMaxMarkers,
|
||||
dark,
|
||||
}: {
|
||||
activeRange: Accessor<number[]>;
|
||||
activeIds: Accessor<number[]>;
|
||||
seriesConfig: SeriesConfig<Scale>;
|
||||
preset: Preset;
|
||||
chart: IChartApi;
|
||||
@@ -399,6 +470,7 @@ function createSeriesGroup<Scale extends ResourceScale>({
|
||||
lastActiveIndex: Accessor<number | undefined>;
|
||||
disabled?: Accessor<boolean>;
|
||||
debouncedSetMinMaxMarkers: VoidFunction;
|
||||
dark: Accessor<boolean>;
|
||||
}) {
|
||||
const {
|
||||
dataset,
|
||||
@@ -417,15 +489,12 @@ function createSeriesGroup<Scale extends ResourceScale>({
|
||||
ISeriesApi<"Baseline" | "Line" | "Histogram" | "Candlestick"> | undefined
|
||||
>[] = new Array(dataset.fetchedJSONs.length);
|
||||
|
||||
let defaultSeriesColor: string | string[] | undefined = undefined;
|
||||
|
||||
const legend = createSeriesLegend({
|
||||
id: stringToId(title),
|
||||
presetId: preset.id,
|
||||
title,
|
||||
seriesList,
|
||||
color: () =>
|
||||
colors || color || defaultSeriesColor || DEFAULT_BASELINE_COLORS,
|
||||
color: colors || color || DEFAULT_BASELINE_COLORS,
|
||||
defaultVisible,
|
||||
disabled,
|
||||
dataset,
|
||||
@@ -448,37 +517,47 @@ function createSeriesGroup<Scale extends ResourceScale>({
|
||||
if (!s) {
|
||||
switch (type) {
|
||||
case SeriesType.Based: {
|
||||
s = createBaseLineSeries(chart, {
|
||||
s = createBaseLineSeries({
|
||||
chart,
|
||||
dark,
|
||||
color,
|
||||
...options,
|
||||
topColor: seriesConfig.topColor,
|
||||
bottomColor: seriesConfig.bottomColor,
|
||||
options,
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
case SeriesType.Candlestick: {
|
||||
const candlestickSeries = createCandlesticksSeries(
|
||||
const candlestickSeries = createCandlesticksSeries({
|
||||
chart,
|
||||
options,
|
||||
);
|
||||
dark,
|
||||
});
|
||||
|
||||
s = candlestickSeries[0];
|
||||
defaultSeriesColor = candlestickSeries[1];
|
||||
|
||||
if (!colors && !color) {
|
||||
legend.color = candlestickSeries[1];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SeriesType.Histogram: {
|
||||
s = createHistogramSeries(chart, {
|
||||
color,
|
||||
...options,
|
||||
s = createHistogramSeries({
|
||||
chart,
|
||||
options,
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
case SeriesType.Line: {
|
||||
s = createLineSeries(chart, {
|
||||
s = createLineSeries({
|
||||
chart,
|
||||
color,
|
||||
...options,
|
||||
dark,
|
||||
options,
|
||||
});
|
||||
|
||||
break;
|
||||
@@ -494,9 +573,7 @@ function createSeriesGroup<Scale extends ResourceScale>({
|
||||
|
||||
s.setData(values);
|
||||
|
||||
untrack(() => {
|
||||
debouncedSetMinMaxMarkers();
|
||||
});
|
||||
debouncedSetMinMaxMarkers();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -522,7 +599,7 @@ function createSeriesGroup<Scale extends ResourceScale>({
|
||||
});
|
||||
|
||||
const inRange = createMemo(() => {
|
||||
const range = activeRange();
|
||||
const range = activeIds();
|
||||
|
||||
if (range.length) {
|
||||
const start = chunkIdToIndex(scale, range.at(0)!);
|
||||
|
||||
@@ -540,7 +540,7 @@ export function createPresets<Scale extends ResourceScale>({
|
||||
bottom: [
|
||||
{
|
||||
title: "Concurrent Liveliness 14d Median",
|
||||
color: `${colors.liveliness}66`,
|
||||
color: colors.darkLiveliness,
|
||||
dataset:
|
||||
params.datasets[scale].concurrent_liveliness_2w_median,
|
||||
},
|
||||
@@ -732,13 +732,13 @@ export function createPresets<Scale extends ResourceScale>({
|
||||
bottom: [
|
||||
{
|
||||
title: "Active Supply Net Change",
|
||||
color: `${colors.liveliness}80`,
|
||||
color: colors.liveliness,
|
||||
dataset: params.datasets[scale].active_supply_3m_net_change,
|
||||
seriesType: SeriesType.Based,
|
||||
},
|
||||
{
|
||||
title: "Vaulted Supply Net Change",
|
||||
color: `${colors.vaultedPrice}80`,
|
||||
color: colors.vaultedPrice,
|
||||
seriesType: SeriesType.Based,
|
||||
dataset:
|
||||
params.datasets[scale].vaulted_supply_3m_net_change,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { phone } from "/src/env";
|
||||
import { createRWS } from "/src/solid/rws";
|
||||
|
||||
import { colors } from "../utils/colors";
|
||||
@@ -32,7 +33,7 @@ export function createPresets(): Presets {
|
||||
name: "Charts",
|
||||
tree: [
|
||||
{
|
||||
name: "By Date",
|
||||
name: "By Block Date",
|
||||
tree: [
|
||||
createMarketPresets("date"),
|
||||
createBlocksPresets(),
|
||||
@@ -57,28 +58,30 @@ export function createPresets(): Presets {
|
||||
],
|
||||
} satisfies PartialPresetFolder,
|
||||
{
|
||||
name: "By Height",
|
||||
tree: [
|
||||
createMarketPresets("height"),
|
||||
createMinersPresets("height"),
|
||||
createTransactionsPresets("height"),
|
||||
...createCohortPresetList({
|
||||
scale: "height",
|
||||
color: colors.bitcoin,
|
||||
name: "",
|
||||
datasetKey: "",
|
||||
title: "",
|
||||
}),
|
||||
createLiquidityFolder({
|
||||
scale: "height",
|
||||
color: colors.bitcoin,
|
||||
datasetKey: "",
|
||||
name: "",
|
||||
}),
|
||||
createHodlersPresets({ scale: "height" }),
|
||||
createAddressesPresets({ scale: "height" }),
|
||||
createCoinblocksPresets({ scale: "height" }),
|
||||
],
|
||||
name: "By Block Height - Desktop/Tablet Only",
|
||||
tree: !phone
|
||||
? [
|
||||
createMarketPresets("height"),
|
||||
createMinersPresets("height"),
|
||||
createTransactionsPresets("height"),
|
||||
...createCohortPresetList({
|
||||
scale: "height",
|
||||
color: colors.bitcoin,
|
||||
name: "",
|
||||
datasetKey: "",
|
||||
title: "",
|
||||
}),
|
||||
createLiquidityFolder({
|
||||
scale: "height",
|
||||
color: colors.bitcoin,
|
||||
datasetKey: "",
|
||||
name: "",
|
||||
}),
|
||||
createHodlersPresets({ scale: "height" }),
|
||||
createAddressesPresets({ scale: "height" }),
|
||||
createCoinblocksPresets({ scale: "height" }),
|
||||
]
|
||||
: [],
|
||||
} satisfies PartialPresetFolder,
|
||||
],
|
||||
},
|
||||
@@ -263,7 +266,14 @@ function checkIfDuplicateIds(ids: string[]) {
|
||||
}
|
||||
|
||||
function findInitialPreset(presets: Preset[]): Preset {
|
||||
const urlPreset = document.location.pathname.substring(1);
|
||||
let urlPreset = document.location.pathname.substring(1);
|
||||
|
||||
if (phone && urlPreset.startsWith("height" satisfies ResourceScale)) {
|
||||
urlPreset = urlPreset.replace(
|
||||
"height" satisfies ResourceScale,
|
||||
"date" satisfies ResourceScale,
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
(urlPreset &&
|
||||
|
||||
@@ -45,7 +45,7 @@ function createPresetFolder({
|
||||
key,
|
||||
}: {
|
||||
scale: ResourceScale;
|
||||
color: string;
|
||||
color: Color;
|
||||
name: string;
|
||||
key: AverageName;
|
||||
}) {
|
||||
|
||||
@@ -12,7 +12,7 @@ export function createCohortPresetFolder<Scale extends ResourceScale>({
|
||||
scale: Scale;
|
||||
name: string;
|
||||
datasetKey: AnyPossibleCohortKey;
|
||||
color: string;
|
||||
color: Color;
|
||||
title: string;
|
||||
}) {
|
||||
return {
|
||||
@@ -38,7 +38,7 @@ export function createCohortPresetList<Scale extends ResourceScale>({
|
||||
scale: Scale;
|
||||
datasetKey: AnyPossibleCohortKey;
|
||||
title: string;
|
||||
color: string;
|
||||
color: Color;
|
||||
}) {
|
||||
const datasetPrefix = datasetKey
|
||||
? (`${datasetKey}_` as const)
|
||||
|
||||
4
app/src/scripts/presets/types.d.ts
vendored
4
app/src/scripts/presets/types.d.ts
vendored
@@ -25,8 +25,8 @@ type ApplyPreset = (params: {
|
||||
datasets: Datasets;
|
||||
preset: Preset;
|
||||
legendSetter: Setter<SeriesLegend[]>;
|
||||
dark: boolean;
|
||||
activeRange: RWS<number[]>;
|
||||
dark: Accessor<boolean>;
|
||||
activeIds: RWS<number[]>;
|
||||
}) => void;
|
||||
|
||||
interface PartialPresetFolder {
|
||||
|
||||
@@ -41,48 +41,129 @@ import {
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// ---
|
||||
|
||||
const lightRed = redTailwind[300];
|
||||
const red = redTailwind[500];
|
||||
const darkRed = redTailwind[900];
|
||||
const orange = orangeTailwind[500];
|
||||
const darkOrange = orangeTailwind[900];
|
||||
const amber = amberTailwind[500];
|
||||
const darkAmber = amberTailwind[900];
|
||||
const yellow = yellowTailwind[500];
|
||||
const darkYellow = yellowTailwind[500];
|
||||
const lime = limeTailwind[500];
|
||||
const darkLime = limeTailwind[900];
|
||||
const green = greenTailwind[500];
|
||||
const darkGreen = greenTailwind[900];
|
||||
const lightEmerald = emeraldTailwind[300];
|
||||
const emerald = emeraldTailwind[500];
|
||||
const darkEmerald = emeraldTailwind[900];
|
||||
const teal = tealTailwind[500];
|
||||
const darkTeal = tealTailwind[900];
|
||||
const cyan = cyanTailwind[500];
|
||||
const darkCyan = cyanTailwind[900];
|
||||
const sky = skyTailwind[500];
|
||||
const darkSky = skyTailwind[900];
|
||||
const blue = blueTailwind[500];
|
||||
const darkBlue = blueTailwind[900];
|
||||
const indigo = indigoTailwind[500];
|
||||
const darkIndigo = indigoTailwind[900];
|
||||
const violet = violetTailwind[500];
|
||||
const darkViolet = violetTailwind[900];
|
||||
const purple = purpleTailwind[500];
|
||||
const darkPurple = purpleTailwind[900];
|
||||
const fuchsia = fuchsiaTailwind[500];
|
||||
const darkFuchsia = fuchsiaTailwind[900];
|
||||
const pink = pinkTailwind[500];
|
||||
const darkPink = pinkTailwind[900];
|
||||
const rose = roseTailwind[500];
|
||||
const darkRose = roseTailwind[900];
|
||||
function lightRed(dark: Accessor<boolean>) {
|
||||
return dark() ? redTailwind[300] : redTailwind[800];
|
||||
}
|
||||
function red(dark: Accessor<boolean>) {
|
||||
return dark() ? redTailwind[500] : redTailwind[600];
|
||||
}
|
||||
function darkRed(dark: Accessor<boolean>) {
|
||||
return dark() ? redTailwind[900] : redTailwind[100];
|
||||
}
|
||||
function orange(dark: Accessor<boolean>) {
|
||||
return dark() ? orangeTailwind[500] : orangeTailwind[600];
|
||||
}
|
||||
function darkOrange(dark: Accessor<boolean>) {
|
||||
return dark() ? orangeTailwind[900] : orangeTailwind[100];
|
||||
}
|
||||
function amber(dark: Accessor<boolean>) {
|
||||
return dark() ? amberTailwind[500] : amberTailwind[600];
|
||||
}
|
||||
function darkAmber(dark: Accessor<boolean>) {
|
||||
return dark() ? amberTailwind[900] : amberTailwind[100];
|
||||
}
|
||||
function yellow(dark: Accessor<boolean>) {
|
||||
return dark() ? yellowTailwind[500] : yellowTailwind[600];
|
||||
}
|
||||
function darkYellow(dark: Accessor<boolean>) {
|
||||
return dark() ? yellowTailwind[500] : yellowTailwind[600];
|
||||
}
|
||||
function lime(dark: Accessor<boolean>) {
|
||||
return dark() ? limeTailwind[500] : limeTailwind[600];
|
||||
}
|
||||
function darkLime(dark: Accessor<boolean>) {
|
||||
return dark() ? limeTailwind[900] : limeTailwind[100];
|
||||
}
|
||||
function green(dark: Accessor<boolean>) {
|
||||
return dark() ? greenTailwind[500] : greenTailwind[600];
|
||||
}
|
||||
function darkGreen(dark: Accessor<boolean>) {
|
||||
return dark() ? greenTailwind[900] : greenTailwind[100];
|
||||
}
|
||||
function lightEmerald(dark: Accessor<boolean>) {
|
||||
return dark() ? emeraldTailwind[300] : emeraldTailwind[800];
|
||||
}
|
||||
function emerald(dark: Accessor<boolean>) {
|
||||
return dark() ? emeraldTailwind[500] : emeraldTailwind[600];
|
||||
}
|
||||
function darkEmerald(dark: Accessor<boolean>) {
|
||||
return dark() ? emeraldTailwind[900] : emeraldTailwind[100];
|
||||
}
|
||||
function teal(dark: Accessor<boolean>) {
|
||||
return dark() ? tealTailwind[500] : tealTailwind[600];
|
||||
}
|
||||
function darkTeal(dark: Accessor<boolean>) {
|
||||
return dark() ? tealTailwind[900] : tealTailwind[100];
|
||||
}
|
||||
function cyan(dark: Accessor<boolean>) {
|
||||
return dark() ? cyanTailwind[500] : cyanTailwind[600];
|
||||
}
|
||||
function darkCyan(dark: Accessor<boolean>) {
|
||||
return dark() ? cyanTailwind[900] : cyanTailwind[100];
|
||||
}
|
||||
function sky(dark: Accessor<boolean>) {
|
||||
return dark() ? skyTailwind[500] : skyTailwind[600];
|
||||
}
|
||||
function darkSky(dark: Accessor<boolean>) {
|
||||
return dark() ? skyTailwind[900] : skyTailwind[100];
|
||||
}
|
||||
function blue(dark: Accessor<boolean>) {
|
||||
return dark() ? blueTailwind[500] : blueTailwind[600];
|
||||
}
|
||||
function darkBlue(dark: Accessor<boolean>) {
|
||||
return dark() ? blueTailwind[900] : blueTailwind[100];
|
||||
}
|
||||
function indigo(dark: Accessor<boolean>) {
|
||||
return dark() ? indigoTailwind[500] : indigoTailwind[600];
|
||||
}
|
||||
function darkIndigo(dark: Accessor<boolean>) {
|
||||
return dark() ? indigoTailwind[900] : indigoTailwind[100];
|
||||
}
|
||||
function violet(dark: Accessor<boolean>) {
|
||||
return dark() ? violetTailwind[500] : violetTailwind[600];
|
||||
}
|
||||
function darkViolet(dark: Accessor<boolean>) {
|
||||
return dark() ? violetTailwind[900] : violetTailwind[100];
|
||||
}
|
||||
function purple(dark: Accessor<boolean>) {
|
||||
return dark() ? purpleTailwind[500] : purpleTailwind[600];
|
||||
}
|
||||
function darkPurple(dark: Accessor<boolean>) {
|
||||
return dark() ? purpleTailwind[900] : purpleTailwind[100];
|
||||
}
|
||||
function fuchsia(dark: Accessor<boolean>) {
|
||||
return dark() ? fuchsiaTailwind[500] : fuchsiaTailwind[600];
|
||||
}
|
||||
function darkFuchsia(dark: Accessor<boolean>) {
|
||||
return dark() ? fuchsiaTailwind[900] : fuchsiaTailwind[100];
|
||||
}
|
||||
function pink(dark: Accessor<boolean>) {
|
||||
return dark() ? pinkTailwind[500] : pinkTailwind[600];
|
||||
}
|
||||
function darkPink(dark: Accessor<boolean>) {
|
||||
return dark() ? pinkTailwind[900] : pinkTailwind[100];
|
||||
}
|
||||
function rose(dark: Accessor<boolean>) {
|
||||
return dark() ? roseTailwind[500] : roseTailwind[600];
|
||||
}
|
||||
function darkRose(dark: Accessor<boolean>) {
|
||||
return dark() ? roseTailwind[900] : roseTailwind[100];
|
||||
}
|
||||
|
||||
const darkWhite = grayTailwind[400];
|
||||
const gray = grayTailwind[600];
|
||||
function darkWhite(dark: Accessor<boolean>) {
|
||||
return dark() ? grayTailwind[400] : grayTailwind[400];
|
||||
}
|
||||
function gray(dark: Accessor<boolean>) {
|
||||
return dark() ? grayTailwind[600] : grayTailwind[400];
|
||||
}
|
||||
|
||||
const black = "#000000";
|
||||
const white = "#ffffff";
|
||||
function white(dark: Accessor<boolean>) {
|
||||
return dark() ? "#ffffff" : "#000000";
|
||||
}
|
||||
|
||||
function black(dark: Accessor<boolean>) {
|
||||
return dark() ? "#000000" : "#ffffff";
|
||||
}
|
||||
|
||||
export const convertCandleToCandleColor = (
|
||||
candle: { close: number; open: number },
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
// import { ONE_DAY_IN_MS } from "./time";
|
||||
|
||||
import { ONE_DAY_IN_MS } from "./time";
|
||||
|
||||
export const dateToString = (date: Date) => date.toJSON().split("T")[0];
|
||||
|
||||
// export const FIVE_MONTHS_IN_DAYS = 30 * 5;
|
||||
|
||||
export const getNumberOfDaysBetweenTwoDates = (oldest: Date, youngest: Date) =>
|
||||
Math.round(Math.abs((youngest.getTime() - oldest.getTime()) / ONE_DAY_IN_MS));
|
||||
|
||||
@@ -3,7 +3,3 @@ export function sleep(ms: number) {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
}
|
||||
|
||||
export function tick() {
|
||||
return sleep(1);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { sleep } from "./sleep";
|
||||
|
||||
export function tick() {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, 0);
|
||||
});
|
||||
return sleep(0);
|
||||
}
|
||||
|
||||
1
app/src/scripts/utils/types.d.ts
vendored
Normal file
1
app/src/scripts/utils/types.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
type Color = (dark: Accessor<boolean>) => string;
|
||||
Reference in New Issue
Block a user