mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 14:49:58 -07:00
website: snapshot
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { ios, canShare } from "../utils/env.js";
|
||||
import { style } from "../utils/elements.js";
|
||||
import { colors } from "./colors.js";
|
||||
import { colors } from "../utils/colors.js";
|
||||
|
||||
export const canCapture = !ios || canShare;
|
||||
|
||||
@@ -90,7 +90,11 @@ export function capture({ screenshot, chartWidth, parent, legends }) {
|
||||
if (hasBottomLegend) {
|
||||
drawLegend(
|
||||
legends.bottom.element,
|
||||
pad + titleOffset + topLegendOffset + screenshot.height + legendHeight / 2,
|
||||
pad +
|
||||
titleOffset +
|
||||
topLegendOffset +
|
||||
screenshot.height +
|
||||
legendHeight / 2,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -99,7 +103,11 @@ export function capture({ screenshot, chartWidth, parent, legends }) {
|
||||
ctx.font = `${fontSize}px ${style.fontFamily}`;
|
||||
ctx.textAlign = "right";
|
||||
ctx.textBaseline = "bottom";
|
||||
ctx.fillText(window.location.host, canvas.width - pad, canvas.height - pad / 2);
|
||||
ctx.fillText(
|
||||
window.location.host,
|
||||
canvas.width - pad,
|
||||
canvas.height - pad / 2,
|
||||
);
|
||||
|
||||
// Open in new tab
|
||||
canvas.toBlob((blob) => {
|
||||
|
||||
@@ -1,249 +0,0 @@
|
||||
import { oklchToRgba } from "./oklch.js";
|
||||
import { dark } from "../utils/theme.js";
|
||||
|
||||
/** @type {Map<string, string>} */
|
||||
const rgbaCache = new Map();
|
||||
|
||||
/**
|
||||
* Convert oklch to rgba with caching
|
||||
* @param {string} color - oklch color string
|
||||
*/
|
||||
function toRgba(color) {
|
||||
if (color === "transparent") return color;
|
||||
const cached = rgbaCache.get(color);
|
||||
if (cached) return cached;
|
||||
const rgba = oklchToRgba(color);
|
||||
rgbaCache.set(color, rgba);
|
||||
return rgba;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce color opacity to 50% for dimming effect
|
||||
* @param {string} color - oklch color string
|
||||
*/
|
||||
function tameColor(color) {
|
||||
if (color === "transparent") return color;
|
||||
return `${color.slice(0, -1)} / 25%)`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} ColorMethods
|
||||
* @property {() => string} tame - Returns tamed (50% opacity) version
|
||||
* @property {(highlighted: boolean) => string} highlight - Returns normal if highlighted, tamed otherwise
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {(() => string) & ColorMethods} Color
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a Color object that is callable and has utility methods
|
||||
* @param {() => string} getter
|
||||
* @returns {Color}
|
||||
*/
|
||||
function createColor(getter) {
|
||||
const color = /** @type {Color} */ (() => toRgba(getter()));
|
||||
color.tame = () => toRgba(tameColor(getter()));
|
||||
color.highlight = (highlighted) =>
|
||||
highlighted ? toRgba(getter()) : toRgba(tameColor(getter()));
|
||||
return color;
|
||||
}
|
||||
|
||||
const globalComputedStyle = getComputedStyle(window.document.documentElement);
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
function getColor(name) {
|
||||
return globalComputedStyle.getPropertyValue(`--${name}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} property
|
||||
*/
|
||||
function getLightDarkValue(property) {
|
||||
const value = globalComputedStyle.getPropertyValue(property);
|
||||
const [light, _dark] = value.slice(11, -1).split(", ");
|
||||
return dark ? _dark : light;
|
||||
}
|
||||
|
||||
const red = createColor(() => getColor("red"));
|
||||
const orange = createColor(() => getColor("orange"));
|
||||
const amber = createColor(() => getColor("amber"));
|
||||
const yellow = createColor(() => getColor("yellow"));
|
||||
const avocado = createColor(() => getColor("avocado"));
|
||||
const lime = createColor(() => getColor("lime"));
|
||||
const green = createColor(() => getColor("green"));
|
||||
const emerald = createColor(() => getColor("emerald"));
|
||||
const teal = createColor(() => getColor("teal"));
|
||||
const cyan = createColor(() => getColor("cyan"));
|
||||
const sky = createColor(() => getColor("sky"));
|
||||
const blue = createColor(() => getColor("blue"));
|
||||
const indigo = createColor(() => getColor("indigo"));
|
||||
const violet = createColor(() => getColor("violet"));
|
||||
const purple = createColor(() => getColor("purple"));
|
||||
const fuchsia = createColor(() => getColor("fuchsia"));
|
||||
const pink = createColor(() => getColor("pink"));
|
||||
const rose = createColor(() => getColor("rose"));
|
||||
|
||||
const spectrumColors = {
|
||||
red,
|
||||
orange,
|
||||
amber,
|
||||
yellow,
|
||||
avocado,
|
||||
lime,
|
||||
green,
|
||||
emerald,
|
||||
teal,
|
||||
cyan,
|
||||
sky,
|
||||
blue,
|
||||
indigo,
|
||||
violet,
|
||||
purple,
|
||||
fuchsia,
|
||||
pink,
|
||||
rose,
|
||||
};
|
||||
|
||||
const baseColors = {
|
||||
default: createColor(() => getLightDarkValue("--color")),
|
||||
gray: createColor(() => getColor("gray")),
|
||||
border: createColor(() => getLightDarkValue("--border-color")),
|
||||
...spectrumColors,
|
||||
};
|
||||
|
||||
export const colors = {
|
||||
...baseColors,
|
||||
|
||||
/** Semantic stat colors for pattern helpers */
|
||||
stat: {
|
||||
sum: blue,
|
||||
cumulative: indigo,
|
||||
avg: orange,
|
||||
max: green,
|
||||
pct90: cyan,
|
||||
pct75: blue,
|
||||
median: yellow,
|
||||
pct25: violet,
|
||||
pct10: fuchsia,
|
||||
min: red,
|
||||
},
|
||||
|
||||
/** Common time period colors */
|
||||
time: {
|
||||
_24h: pink,
|
||||
_1w: red,
|
||||
_1m: yellow,
|
||||
_1y: lime,
|
||||
all: teal,
|
||||
},
|
||||
|
||||
/** DCA period colors by term */
|
||||
dcaPeriods: {
|
||||
// Short term
|
||||
_1w: red,
|
||||
_1m: orange,
|
||||
_3m: yellow,
|
||||
_6m: lime,
|
||||
// Medium term
|
||||
_1y: green,
|
||||
_2y: teal,
|
||||
_3y: cyan,
|
||||
// Long term
|
||||
_4y: sky,
|
||||
_5y: blue,
|
||||
_6y: indigo,
|
||||
_8y: violet,
|
||||
_10y: purple,
|
||||
},
|
||||
|
||||
/** DCA year colors by halving epoch */
|
||||
dcaYears: {
|
||||
// Epoch 5 (2024+)
|
||||
_2026: rose,
|
||||
_2025: fuchsia,
|
||||
_2024: purple,
|
||||
// Epoch 4 (2020-2023)
|
||||
_2023: violet,
|
||||
_2022: blue,
|
||||
_2021: sky,
|
||||
_2020: teal,
|
||||
// Epoch 3 (2016-2019)
|
||||
_2019: green,
|
||||
_2018: yellow,
|
||||
_2017: orange,
|
||||
_2016: red,
|
||||
_2015: pink,
|
||||
},
|
||||
|
||||
/** Returns/lookback colors by period */
|
||||
returns: {
|
||||
_1d: red,
|
||||
_1w: orange,
|
||||
_1m: yellow,
|
||||
_3m: lime,
|
||||
_6m: green,
|
||||
_1y: teal,
|
||||
_2y: cyan,
|
||||
_3y: sky,
|
||||
_4y: blue,
|
||||
_5y: indigo,
|
||||
_6y: violet,
|
||||
_8y: purple,
|
||||
_10y: fuchsia,
|
||||
},
|
||||
|
||||
/** Moving average colors by period */
|
||||
ma: {
|
||||
_1w: red,
|
||||
_8d: orange,
|
||||
_12d: amber,
|
||||
_13d: amber,
|
||||
_21d: yellow,
|
||||
_26d: lime,
|
||||
_1m: lime,
|
||||
_34d: green,
|
||||
_55d: emerald,
|
||||
_89d: teal,
|
||||
_111d: cyan,
|
||||
_144d: sky,
|
||||
_200d: blue,
|
||||
_350d: indigo,
|
||||
_1y: violet,
|
||||
_2y: purple,
|
||||
_200w: fuchsia,
|
||||
_4y: pink,
|
||||
},
|
||||
|
||||
/** Script type colors (oldest to newest) */
|
||||
scriptType: {
|
||||
p2pk65: red,
|
||||
p2pk33: orange,
|
||||
p2pkh: yellow,
|
||||
p2ms: lime,
|
||||
p2sh: green,
|
||||
p2wpkh: teal,
|
||||
p2wsh: blue,
|
||||
p2tr: indigo,
|
||||
p2a: purple,
|
||||
opreturn: pink,
|
||||
unknown: violet,
|
||||
empty: fuchsia,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {typeof colors} Colors
|
||||
* @typedef {keyof typeof baseColors} ColorName
|
||||
*/
|
||||
|
||||
/** Palette for indexed series */
|
||||
const palette = Object.values(spectrumColors);
|
||||
|
||||
/**
|
||||
* Get a color by index (cycles through palette)
|
||||
* @param {number} index
|
||||
*/
|
||||
export const colorAt = (index) => palette[index % palette.length];
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
} from "../modules/lightweight-charts/5.1.0/dist/lightweight-charts.standalone.production.mjs";
|
||||
import { createLegend } from "./legend.js";
|
||||
import { capture } from "./capture.js";
|
||||
import { colors } from "./colors.js";
|
||||
import { colors } from "../utils/colors.js";
|
||||
import { createRadios, createSelect } from "../utils/dom.js";
|
||||
import { createPersistedValue } from "../utils/persisted.js";
|
||||
import { onChange as onThemeChange } from "../utils/theme.js";
|
||||
|
||||
Reference in New Issue
Block a user