mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-21 07:58:11 -07:00
website: snapshot
This commit is contained in:
@@ -22,7 +22,7 @@ function toRgba(color) {
|
|||||||
*/
|
*/
|
||||||
function tameColor(color) {
|
function tameColor(color) {
|
||||||
if (color === "transparent") return color;
|
if (color === "transparent") return color;
|
||||||
return `${color.slice(0, -1)} / 50%)`;
|
return `${color.slice(0, -1)} / 25%)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+234
-100
@@ -36,7 +36,11 @@ import { resources } from "../resources.js";
|
|||||||
* @property {string} id
|
* @property {string} id
|
||||||
* @property {number} paneIndex
|
* @property {number} paneIndex
|
||||||
* @property {Signal<boolean>} active
|
* @property {Signal<boolean>} active
|
||||||
* @property {Signal<boolean>} highlighted
|
* @property {() => void} show
|
||||||
|
* @property {() => void} hide
|
||||||
|
* @property {(order: number) => void} setOrder
|
||||||
|
* @property {() => void} highlight
|
||||||
|
* @property {() => void} tame
|
||||||
* @property {() => boolean} hasData
|
* @property {() => boolean} hasData
|
||||||
* @property {Signal<string | null>} url
|
* @property {Signal<string | null>} url
|
||||||
* @property {() => readonly T[]} getData
|
* @property {() => readonly T[]} getData
|
||||||
@@ -165,23 +169,19 @@ export function createChart({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const visibleBarsCount = signals.createSignal(
|
/** @typedef {(visibleBarsCount: number) => void} ZoomChangeCallback */
|
||||||
initialVisibleBarsCount ?? Infinity,
|
|
||||||
);
|
let visibleBarsCount = initialVisibleBarsCount ?? Infinity;
|
||||||
/** @type {() => 0 | 1 | 2 | 3} 0: <=200, 1: <=500, 2: <=1000, 3: >1000 */
|
/** @type {Set<ZoomChangeCallback>} */
|
||||||
const visibleBarsCountBucket = signals.createMemo(() => {
|
const onZoomChange = new Set();
|
||||||
const count = visibleBarsCount();
|
|
||||||
return count > 1000 ? 3 : count > 500 ? 2 : count > 200 ? 1 : 0;
|
|
||||||
});
|
|
||||||
const shouldShowLine = signals.createMemo(
|
|
||||||
() => visibleBarsCountBucket() >= 2,
|
|
||||||
);
|
|
||||||
|
|
||||||
ichart.timeScale().subscribeVisibleLogicalRangeChange(
|
ichart.timeScale().subscribeVisibleLogicalRangeChange(
|
||||||
throttle((range) => {
|
throttle((range) => {
|
||||||
if (range) {
|
if (!range) return;
|
||||||
visibleBarsCount.set(range.to - range.from);
|
const count = range.to - range.from;
|
||||||
}
|
if (count === visibleBarsCount) return;
|
||||||
|
visibleBarsCount = count;
|
||||||
|
onZoomChange.forEach((cb) => cb(count));
|
||||||
}, 100),
|
}, 100),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -360,7 +360,11 @@ export function createChart({
|
|||||||
* @param {Accessor<WhitespaceData[]>} [args.data]
|
* @param {Accessor<WhitespaceData[]>} [args.data]
|
||||||
* @param {number} args.paneIndex
|
* @param {number} args.paneIndex
|
||||||
* @param {boolean} [args.defaultActive]
|
* @param {boolean} [args.defaultActive]
|
||||||
* @param {(ctx: { active: Signal<boolean>, highlighted: Signal<boolean>, zOrder: number }) => void} args.setup
|
* @param {(order: number) => void} args.setOrder
|
||||||
|
* @param {() => void} args.show
|
||||||
|
* @param {() => void} args.hide
|
||||||
|
* @param {() => void} args.highlight
|
||||||
|
* @param {() => void} args.tame
|
||||||
* @param {() => readonly any[]} args.getData
|
* @param {() => readonly any[]} args.getData
|
||||||
* @param {(data: any[]) => void} args.setData
|
* @param {(data: any[]) => void} args.setData
|
||||||
* @param {(data: any) => void} args.update
|
* @param {(data: any) => void} args.update
|
||||||
@@ -376,7 +380,11 @@ export function createChart({
|
|||||||
defaultActive,
|
defaultActive,
|
||||||
colors,
|
colors,
|
||||||
data,
|
data,
|
||||||
setup,
|
setOrder,
|
||||||
|
show,
|
||||||
|
hide,
|
||||||
|
highlight,
|
||||||
|
tame,
|
||||||
getData,
|
getData,
|
||||||
setData,
|
setData,
|
||||||
update,
|
update,
|
||||||
@@ -398,9 +406,12 @@ export function createChart({
|
|||||||
sharedActiveSignals.set(urlId, active);
|
sharedActiveSignals.set(urlId, active);
|
||||||
}
|
}
|
||||||
|
|
||||||
const highlighted = signals.createSignal(true);
|
setOrder(-order);
|
||||||
|
|
||||||
setup({ active, highlighted, zOrder: -order });
|
// Bridge signal to series methods
|
||||||
|
signals.createEffect(active, (isActive) => {
|
||||||
|
isActive ? show() : hide();
|
||||||
|
});
|
||||||
|
|
||||||
let hasData = false;
|
let hasData = false;
|
||||||
let lastTime = -Infinity;
|
let lastTime = -Infinity;
|
||||||
@@ -411,7 +422,11 @@ export function createChart({
|
|||||||
/** @type {AnySeries} */
|
/** @type {AnySeries} */
|
||||||
const series = {
|
const series = {
|
||||||
active,
|
active,
|
||||||
highlighted,
|
setOrder,
|
||||||
|
show,
|
||||||
|
hide,
|
||||||
|
highlight,
|
||||||
|
tame,
|
||||||
hasData: () => hasData,
|
hasData: () => hasData,
|
||||||
id,
|
id,
|
||||||
paneIndex,
|
paneIndex,
|
||||||
@@ -693,13 +708,40 @@ export function createChart({
|
|||||||
color: colors.default(),
|
color: colors.default(),
|
||||||
lineWidth,
|
lineWidth,
|
||||||
visible: false,
|
visible: false,
|
||||||
priceLineVisible: false,
|
priceLineVisible: true,
|
||||||
},
|
},
|
||||||
paneIndex,
|
paneIndex,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
let showLine = false;
|
let active = true;
|
||||||
|
let highlighted = true;
|
||||||
|
let showLine = visibleBarsCount > 500;
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
candlestickISeries.applyOptions({
|
||||||
|
visible: active && !showLine,
|
||||||
|
lastValueVisible: highlighted,
|
||||||
|
upColor: upColor.highlight(highlighted),
|
||||||
|
downColor: downColor.highlight(highlighted),
|
||||||
|
wickUpColor: upColor.highlight(highlighted),
|
||||||
|
wickDownColor: downColor.highlight(highlighted),
|
||||||
|
});
|
||||||
|
lineISeries.applyOptions({
|
||||||
|
visible: active && showLine,
|
||||||
|
lastValueVisible: highlighted,
|
||||||
|
color: colors.default.highlight(highlighted),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {ZoomChangeCallback} */
|
||||||
|
function handleZoom(count) {
|
||||||
|
const newShowLine = count > 500;
|
||||||
|
if (newShowLine === showLine) return;
|
||||||
|
showLine = newShowLine;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
onZoomChange.add(handleZoom);
|
||||||
|
|
||||||
const series = addSeries({
|
const series = addSeries({
|
||||||
colors: [upColor, downColor],
|
colors: [upColor, downColor],
|
||||||
@@ -711,30 +753,29 @@ export function createChart({
|
|||||||
data,
|
data,
|
||||||
defaultActive,
|
defaultActive,
|
||||||
metric,
|
metric,
|
||||||
setup: ({ active, highlighted, zOrder }) => {
|
setOrder(order) {
|
||||||
candlestickISeries.setSeriesOrder(zOrder);
|
candlestickISeries.setSeriesOrder(order);
|
||||||
lineISeries.setSeriesOrder(zOrder);
|
lineISeries.setSeriesOrder(order);
|
||||||
signals.createEffect(
|
},
|
||||||
() => ({
|
show() {
|
||||||
shouldShow: shouldShowLine(),
|
if (active) return;
|
||||||
active: active(),
|
active = true;
|
||||||
highlighted: highlighted(),
|
update();
|
||||||
}),
|
},
|
||||||
({ shouldShow, active, highlighted }) => {
|
hide() {
|
||||||
showLine = shouldShow;
|
if (!active) return;
|
||||||
candlestickISeries.applyOptions({
|
active = false;
|
||||||
visible: active && !showLine,
|
update();
|
||||||
upColor: upColor.highlight(highlighted),
|
},
|
||||||
downColor: downColor.highlight(highlighted),
|
highlight() {
|
||||||
wickUpColor: upColor.highlight(highlighted),
|
if (highlighted) return;
|
||||||
wickDownColor: downColor.highlight(highlighted),
|
highlighted = true;
|
||||||
});
|
update();
|
||||||
lineISeries.applyOptions({
|
},
|
||||||
visible: active && showLine,
|
tame() {
|
||||||
color: colors.default.highlight(highlighted),
|
if (!highlighted) return;
|
||||||
});
|
highlighted = false;
|
||||||
},
|
update();
|
||||||
);
|
|
||||||
},
|
},
|
||||||
setData: (data) => {
|
setData: (data) => {
|
||||||
candlestickISeries.setData(data);
|
candlestickISeries.setData(data);
|
||||||
@@ -747,6 +788,7 @@ export function createChart({
|
|||||||
},
|
},
|
||||||
getData: () => candlestickISeries.data(),
|
getData: () => candlestickISeries.data(),
|
||||||
onRemove: () => {
|
onRemove: () => {
|
||||||
|
onZoomChange.delete(handleZoom);
|
||||||
ichart.removeSeries(candlestickISeries);
|
ichart.removeSeries(candlestickISeries);
|
||||||
ichart.removeSeries(lineISeries);
|
ichart.removeSeries(lineISeries);
|
||||||
},
|
},
|
||||||
@@ -794,6 +836,17 @@ export function createChart({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let active = true;
|
||||||
|
let highlighted = true;
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
iseries.applyOptions({
|
||||||
|
visible: active,
|
||||||
|
lastValueVisible: highlighted,
|
||||||
|
color: positiveColor.highlight(highlighted),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const series = addSeries({
|
const series = addSeries({
|
||||||
colors: isDualColor ? [positiveColor, negativeColor] : [positiveColor],
|
colors: isDualColor ? [positiveColor, negativeColor] : [positiveColor],
|
||||||
name,
|
name,
|
||||||
@@ -804,17 +857,26 @@ export function createChart({
|
|||||||
data,
|
data,
|
||||||
defaultActive,
|
defaultActive,
|
||||||
metric,
|
metric,
|
||||||
setup: ({ active, highlighted, zOrder }) => {
|
setOrder: (order) => iseries.setSeriesOrder(order),
|
||||||
iseries.setSeriesOrder(zOrder);
|
show() {
|
||||||
signals.createEffect(
|
if (active) return;
|
||||||
() => ({ active: active(), highlighted: highlighted() }),
|
active = true;
|
||||||
({ active, highlighted }) => {
|
update();
|
||||||
iseries.applyOptions({
|
},
|
||||||
visible: active,
|
hide() {
|
||||||
color: positiveColor.highlight(highlighted),
|
if (!active) return;
|
||||||
});
|
active = false;
|
||||||
},
|
update();
|
||||||
);
|
},
|
||||||
|
highlight() {
|
||||||
|
if (highlighted) return;
|
||||||
|
highlighted = true;
|
||||||
|
update();
|
||||||
|
},
|
||||||
|
tame() {
|
||||||
|
if (!highlighted) return;
|
||||||
|
highlighted = false;
|
||||||
|
update();
|
||||||
},
|
},
|
||||||
setData: (data) => {
|
setData: (data) => {
|
||||||
if (isDualColor) {
|
if (isDualColor) {
|
||||||
@@ -854,13 +916,14 @@ export function createChart({
|
|||||||
name,
|
name,
|
||||||
unit,
|
unit,
|
||||||
order,
|
order,
|
||||||
color,
|
color: _color,
|
||||||
paneIndex = 0,
|
paneIndex = 0,
|
||||||
defaultActive,
|
defaultActive,
|
||||||
data,
|
data,
|
||||||
options,
|
options,
|
||||||
}) {
|
}) {
|
||||||
color ||= unit.id === "usd" ? colors.green : colors.orange;
|
const color =
|
||||||
|
_color ?? (unit.id === "usd" ? colors.green : colors.orange);
|
||||||
|
|
||||||
/** @type {LineISeries} */
|
/** @type {LineISeries} */
|
||||||
const iseries = /** @type {any} */ (
|
const iseries = /** @type {any} */ (
|
||||||
@@ -877,6 +940,17 @@ export function createChart({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let active = true;
|
||||||
|
let highlighted = true;
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
iseries.applyOptions({
|
||||||
|
visible: active,
|
||||||
|
lastValueVisible: highlighted,
|
||||||
|
color: color.highlight(highlighted),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const series = addSeries({
|
const series = addSeries({
|
||||||
colors: [color],
|
colors: [color],
|
||||||
name,
|
name,
|
||||||
@@ -887,17 +961,26 @@ export function createChart({
|
|||||||
data,
|
data,
|
||||||
defaultActive,
|
defaultActive,
|
||||||
metric,
|
metric,
|
||||||
setup: ({ active, highlighted, zOrder }) => {
|
setOrder: (order) => iseries.setSeriesOrder(order),
|
||||||
iseries.setSeriesOrder(zOrder);
|
show() {
|
||||||
signals.createEffect(
|
if (active) return;
|
||||||
() => ({ active: active(), highlighted: highlighted() }),
|
active = true;
|
||||||
({ active, highlighted }) => {
|
update();
|
||||||
iseries.applyOptions({
|
},
|
||||||
visible: active,
|
hide() {
|
||||||
color: color.highlight(highlighted),
|
if (!active) return;
|
||||||
});
|
active = false;
|
||||||
},
|
update();
|
||||||
);
|
},
|
||||||
|
highlight() {
|
||||||
|
if (highlighted) return;
|
||||||
|
highlighted = true;
|
||||||
|
update();
|
||||||
|
},
|
||||||
|
tame() {
|
||||||
|
if (!highlighted) return;
|
||||||
|
highlighted = false;
|
||||||
|
update();
|
||||||
},
|
},
|
||||||
setData: (data) => iseries.setData(data),
|
setData: (data) => iseries.setData(data),
|
||||||
update: (data) => iseries.update(data),
|
update: (data) => iseries.update(data),
|
||||||
@@ -923,13 +1006,14 @@ export function createChart({
|
|||||||
name,
|
name,
|
||||||
unit,
|
unit,
|
||||||
order,
|
order,
|
||||||
color,
|
color: _color,
|
||||||
paneIndex = 0,
|
paneIndex = 0,
|
||||||
defaultActive,
|
defaultActive,
|
||||||
data,
|
data,
|
||||||
options,
|
options,
|
||||||
}) {
|
}) {
|
||||||
color ||= unit.id === "usd" ? colors.green : colors.orange;
|
const color =
|
||||||
|
_color ?? (unit.id === "usd" ? colors.green : colors.orange);
|
||||||
|
|
||||||
/** @type {LineISeries} */
|
/** @type {LineISeries} */
|
||||||
const iseries = /** @type {any} */ (
|
const iseries = /** @type {any} */ (
|
||||||
@@ -948,6 +1032,28 @@ export function createChart({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let active = true;
|
||||||
|
let highlighted = true;
|
||||||
|
let radius =
|
||||||
|
visibleBarsCount > 1000 ? 1 : visibleBarsCount > 200 ? 1.5 : 2;
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
iseries.applyOptions({
|
||||||
|
visible: active,
|
||||||
|
lastValueVisible: highlighted,
|
||||||
|
color: color.highlight(highlighted),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {ZoomChangeCallback} */
|
||||||
|
function handleZoom(count) {
|
||||||
|
const newRadius = count > 1000 ? 1 : count > 200 ? 1.5 : 2;
|
||||||
|
if (newRadius === radius) return;
|
||||||
|
radius = newRadius;
|
||||||
|
iseries.applyOptions({ pointMarkersRadius: radius });
|
||||||
|
}
|
||||||
|
onZoomChange.add(handleZoom);
|
||||||
|
|
||||||
const series = addSeries({
|
const series = addSeries({
|
||||||
colors: [color],
|
colors: [color],
|
||||||
name,
|
name,
|
||||||
@@ -958,26 +1064,34 @@ export function createChart({
|
|||||||
data,
|
data,
|
||||||
defaultActive,
|
defaultActive,
|
||||||
metric,
|
metric,
|
||||||
setup: ({ active, highlighted, zOrder }) => {
|
setOrder: (order) => iseries.setSeriesOrder(order),
|
||||||
iseries.setSeriesOrder(zOrder);
|
show() {
|
||||||
signals.createEffect(
|
if (active) return;
|
||||||
() => ({ active: active(), highlighted: highlighted() }),
|
active = true;
|
||||||
({ active, highlighted }) => {
|
update();
|
||||||
iseries.applyOptions({
|
},
|
||||||
visible: active,
|
hide() {
|
||||||
color: color.highlight(highlighted),
|
if (!active) return;
|
||||||
});
|
active = false;
|
||||||
},
|
update();
|
||||||
);
|
},
|
||||||
signals.createEffect(visibleBarsCountBucket, (bucket) => {
|
highlight() {
|
||||||
const radius = bucket === 3 ? 1 : bucket >= 1 ? 1.5 : 2;
|
if (highlighted) return;
|
||||||
iseries.applyOptions({ pointMarkersRadius: radius });
|
highlighted = true;
|
||||||
});
|
update();
|
||||||
|
},
|
||||||
|
tame() {
|
||||||
|
if (!highlighted) return;
|
||||||
|
highlighted = false;
|
||||||
|
update();
|
||||||
},
|
},
|
||||||
setData: (data) => iseries.setData(data),
|
setData: (data) => iseries.setData(data),
|
||||||
update: (data) => iseries.update(data),
|
update: (data) => iseries.update(data),
|
||||||
getData: () => iseries.data(),
|
getData: () => iseries.data(),
|
||||||
onRemove: () => ichart.removeSeries(iseries),
|
onRemove: () => {
|
||||||
|
onZoomChange.delete(handleZoom);
|
||||||
|
ichart.removeSeries(iseries);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
return series;
|
return series;
|
||||||
},
|
},
|
||||||
@@ -1032,6 +1146,18 @@ export function createChart({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let active = true;
|
||||||
|
let highlighted = true;
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
iseries.applyOptions({
|
||||||
|
visible: active,
|
||||||
|
lastValueVisible: highlighted,
|
||||||
|
topLineColor: topColor.highlight(highlighted),
|
||||||
|
bottomLineColor: bottomColor.highlight(highlighted),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const series = addSeries({
|
const series = addSeries({
|
||||||
colors: [topColor, bottomColor],
|
colors: [topColor, bottomColor],
|
||||||
name,
|
name,
|
||||||
@@ -1042,18 +1168,26 @@ export function createChart({
|
|||||||
data,
|
data,
|
||||||
defaultActive,
|
defaultActive,
|
||||||
metric,
|
metric,
|
||||||
setup: ({ active, highlighted, zOrder }) => {
|
setOrder: (order) => iseries.setSeriesOrder(order),
|
||||||
iseries.setSeriesOrder(zOrder);
|
show() {
|
||||||
signals.createEffect(
|
if (active) return;
|
||||||
() => ({ active: active(), highlighted: highlighted() }),
|
active = true;
|
||||||
({ active, highlighted }) => {
|
update();
|
||||||
iseries.applyOptions({
|
},
|
||||||
visible: active,
|
hide() {
|
||||||
topLineColor: topColor.highlight(highlighted),
|
if (!active) return;
|
||||||
bottomLineColor: bottomColor.highlight(highlighted),
|
active = false;
|
||||||
});
|
update();
|
||||||
},
|
},
|
||||||
);
|
highlight() {
|
||||||
|
if (highlighted) return;
|
||||||
|
highlighted = true;
|
||||||
|
update();
|
||||||
|
},
|
||||||
|
tame() {
|
||||||
|
if (!highlighted) return;
|
||||||
|
highlighted = false;
|
||||||
|
update();
|
||||||
},
|
},
|
||||||
setData: (data) => iseries.setData(data),
|
setData: (data) => iseries.setData(data),
|
||||||
update: (data) => iseries.update(data),
|
update: (data) => iseries.update(data),
|
||||||
|
|||||||
@@ -7,7 +7,23 @@ import { stringToId } from "../utils/format.js";
|
|||||||
export function createLegend(signals) {
|
export function createLegend(signals) {
|
||||||
const element = window.document.createElement("legend");
|
const element = window.document.createElement("legend");
|
||||||
|
|
||||||
const hovered = signals.createSignal(/** @type {AnySeries | null} */ (null));
|
/** @type {AnySeries | null} */
|
||||||
|
let hoveredSeries = null;
|
||||||
|
/** @type {Map<AnySeries, { span: HTMLSpanElement, color: Color }[]>} */
|
||||||
|
const seriesColorSpans = new Map();
|
||||||
|
|
||||||
|
/** @param {AnySeries | null} series */
|
||||||
|
function setHovered(series) {
|
||||||
|
if (hoveredSeries === series) return;
|
||||||
|
hoveredSeries = series;
|
||||||
|
for (const [entrySeries, colorSpans] of seriesColorSpans) {
|
||||||
|
const shouldHighlight = !hoveredSeries || hoveredSeries === entrySeries;
|
||||||
|
shouldHighlight ? entrySeries.highlight() : entrySeries.tame();
|
||||||
|
for (const { span, color } of colorSpans) {
|
||||||
|
span.style.backgroundColor = color.highlight(shouldHighlight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @type {HTMLElement[]} */
|
/** @type {HTMLElement[]} */
|
||||||
const legends = [];
|
const legends = [];
|
||||||
@@ -62,37 +78,21 @@ export function createLegend(signals) {
|
|||||||
spanMain.append(spanName);
|
spanMain.append(spanName);
|
||||||
|
|
||||||
div.append(label);
|
div.append(label);
|
||||||
label.addEventListener("mouseover", () => {
|
label.addEventListener("mouseover", () => setHovered(series));
|
||||||
const h = hovered();
|
label.addEventListener("mouseleave", () => setHovered(null));
|
||||||
if (!h || h !== series) {
|
|
||||||
hovered.set(series);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
label.addEventListener("mouseleave", () => {
|
|
||||||
hovered.set(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
const shouldHighlight = () => !hovered() || hovered() === series;
|
|
||||||
|
|
||||||
// Update series highlighted state
|
|
||||||
signals.createEffect(shouldHighlight, (shouldHighlight) => {
|
|
||||||
series.highlighted.set(shouldHighlight);
|
|
||||||
});
|
|
||||||
|
|
||||||
const spanColors = window.document.createElement("span");
|
const spanColors = window.document.createElement("span");
|
||||||
spanColors.classList.add("colors");
|
spanColors.classList.add("colors");
|
||||||
spanMain.prepend(spanColors);
|
spanMain.prepend(spanColors);
|
||||||
|
/** @type {{ span: HTMLSpanElement, color: Color }[]} */
|
||||||
|
const colorSpans = [];
|
||||||
colors.forEach((color) => {
|
colors.forEach((color) => {
|
||||||
const spanColor = window.document.createElement("span");
|
const spanColor = window.document.createElement("span");
|
||||||
|
spanColor.style.backgroundColor = color.highlight(true);
|
||||||
spanColors.append(spanColor);
|
spanColors.append(spanColor);
|
||||||
|
colorSpans.push({ span: spanColor, color });
|
||||||
signals.createEffect(
|
|
||||||
() => color.highlight(shouldHighlight()),
|
|
||||||
(c) => {
|
|
||||||
spanColor.style.backgroundColor = c;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
seriesColorSpans.set(series, colorSpans);
|
||||||
|
|
||||||
const anchor = window.document.createElement("a");
|
const anchor = window.document.createElement("a");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user