mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-08 14:11:56 -07:00
website: snapshot
This commit is contained in:
@@ -92,19 +92,20 @@ export function createChart({
|
||||
config,
|
||||
}) {
|
||||
// Chart owns its index state
|
||||
/** @type {Signal<ChartableIndexName>} */
|
||||
const indexName = signals.createPersistedSignal({
|
||||
/** @type {Set<(index: ChartableIndex) => void>} */
|
||||
const onIndexChange = new Set();
|
||||
|
||||
const index = () => serdeChartableIndex.deserialize(indexName.value);
|
||||
|
||||
const indexName = createPersistedValue({
|
||||
defaultValue: /** @type {ChartableIndexName} */ ("date"),
|
||||
storageKey: "chart-index",
|
||||
urlKey: "i",
|
||||
serialize: (v) => v,
|
||||
deserialize: (s) => /** @type {ChartableIndexName} */ (s),
|
||||
onChange: () => onIndexChange.forEach((cb) => cb(index())),
|
||||
});
|
||||
|
||||
const index = signals.createMemo(() =>
|
||||
serdeChartableIndex.deserialize(indexName()),
|
||||
);
|
||||
|
||||
// Range state: localStorage stores all ranges per-index, URL stores current range only
|
||||
/** @typedef {{ from: number, to: number }} Range */
|
||||
const ranges = createPersistedValue({
|
||||
@@ -126,11 +127,11 @@ export function createChart({
|
||||
});
|
||||
|
||||
/** @returns {Range | null} */
|
||||
const getRange = () => range.value ?? ranges.value[indexName()] ?? null;
|
||||
const getRange = () => range.value ?? ranges.value[indexName.value] ?? null;
|
||||
|
||||
/** @param {Range} value */
|
||||
const setRange = (value) => {
|
||||
ranges.set({ ...ranges.value, [indexName()]: value });
|
||||
ranges.set({ ...ranges.value, [indexName.value]: value });
|
||||
range.set(value);
|
||||
};
|
||||
|
||||
@@ -264,7 +265,8 @@ export function createChart({
|
||||
applyColors();
|
||||
const removeThemeListener = onThemeChange(applyColors);
|
||||
|
||||
signals.createEffect(index, (index) => {
|
||||
/** @param {ChartableIndex} index */
|
||||
function applyIndexSettings(index) {
|
||||
const minBarSpacing =
|
||||
index === "monthindex"
|
||||
? 1
|
||||
@@ -288,7 +290,9 @@ export function createChart({
|
||||
: {}),
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
applyIndexSettings(index());
|
||||
onIndexChange.add(applyIndexSettings);
|
||||
|
||||
const activeResources = /** @type {Set<MetricResource<unknown>>} */ (
|
||||
new Set()
|
||||
@@ -314,39 +318,42 @@ export function createChart({
|
||||
* @param {(pane: IPaneApi<Time>) => HTMLElement} args.createChild
|
||||
*/
|
||||
function addFieldsetIfNeeded({ paneIndex, id, position, createChild }) {
|
||||
setTimeout(() => {
|
||||
const parent = ichart
|
||||
?.panes()
|
||||
.at(paneIndex)
|
||||
?.getHTMLElement()
|
||||
?.children?.item(1)?.firstChild;
|
||||
setTimeout(
|
||||
() => {
|
||||
const parent = ichart
|
||||
?.panes()
|
||||
.at(paneIndex)
|
||||
?.getHTMLElement()
|
||||
?.children?.item(1)?.firstChild;
|
||||
|
||||
if (!parent) throw Error("Parent should exist");
|
||||
if (!parent) throw Error("Parent should exist");
|
||||
|
||||
const children = Array.from(parent.childNodes).filter(
|
||||
(element) =>
|
||||
/** @type {HTMLElement} */ (element).dataset.position === position,
|
||||
);
|
||||
const children = Array.from(parent.childNodes).filter(
|
||||
(element) =>
|
||||
/** @type {HTMLElement} */ (element).dataset.position === position,
|
||||
);
|
||||
|
||||
if (children.length === 1) {
|
||||
children[0].remove();
|
||||
} else if (children.length > 1) {
|
||||
throw Error("Untraceable");
|
||||
}
|
||||
if (children.length === 1) {
|
||||
children[0].remove();
|
||||
} else if (children.length > 1) {
|
||||
throw Error("Untraceable");
|
||||
}
|
||||
|
||||
const fieldset = window.document.createElement("fieldset");
|
||||
fieldset.dataset.size = "xs";
|
||||
fieldset.dataset.position = position;
|
||||
fieldset.id = `${id}-${paneIndex}`;
|
||||
const pane = ichart.panes().at(paneIndex);
|
||||
if (!pane) throw Error("Expect pane");
|
||||
pane
|
||||
.getHTMLElement()
|
||||
?.children?.item(1)
|
||||
?.firstChild?.appendChild(fieldset);
|
||||
const fieldset = window.document.createElement("fieldset");
|
||||
fieldset.dataset.size = "xs";
|
||||
fieldset.dataset.position = position;
|
||||
fieldset.id = `${id}-${paneIndex}`;
|
||||
const pane = ichart.panes().at(paneIndex);
|
||||
if (!pane) throw Error("Expect pane");
|
||||
pane
|
||||
.getHTMLElement()
|
||||
?.children?.item(1)
|
||||
?.firstChild?.appendChild(fieldset);
|
||||
|
||||
fieldset.append(createChild(pane));
|
||||
}, paneIndex ? 50 : 0);
|
||||
fieldset.append(createChild(pane));
|
||||
},
|
||||
paneIndex ? 50 : 0,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
createShadow,
|
||||
createReactiveChoiceField,
|
||||
createChoiceField,
|
||||
createHeader,
|
||||
} from "../utils/dom.js";
|
||||
import { chartElement } from "../utils/elements.js";
|
||||
@@ -430,25 +431,26 @@ function createIndexSelector(option, chart) {
|
||||
);
|
||||
});
|
||||
|
||||
/** @type {ChartableIndexName} */
|
||||
const defaultIndex = "date";
|
||||
const field = createReactiveChoiceField({
|
||||
defaultValue: defaultIndex,
|
||||
selected: chart.indexName,
|
||||
choices,
|
||||
id: "index",
|
||||
signals,
|
||||
});
|
||||
|
||||
const fieldset = window.document.createElement("fieldset");
|
||||
fieldset.id = "interval";
|
||||
fieldset.dataset.size = "sm";
|
||||
|
||||
const screenshotSpan = window.document.createElement("span");
|
||||
screenshotSpan.innerText = "interval:";
|
||||
fieldset.append(screenshotSpan);
|
||||
|
||||
fieldset.append(field);
|
||||
fieldset.dataset.size = "sm";
|
||||
/** @type {HTMLElement | null} */
|
||||
let field = null;
|
||||
signals.createEffect(choices, (newChoices) => {
|
||||
if (field) field.remove();
|
||||
field = createChoiceField({
|
||||
initialValue: chart.indexName.value,
|
||||
onChange: (v) => chart.indexName.set(v),
|
||||
choices: newChoices,
|
||||
id: "index",
|
||||
});
|
||||
fieldset.append(field);
|
||||
});
|
||||
|
||||
return fieldset;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { debounce } from "./timing.js";
|
||||
* @param {(v: T) => string} args.serialize
|
||||
* @param {(s: string) => T} args.deserialize
|
||||
* @param {boolean} [args.saveDefaultValue]
|
||||
* @param {(v: T) => void} [args.onChange]
|
||||
*/
|
||||
export function createPersistedValue({
|
||||
defaultValue,
|
||||
@@ -19,6 +20,7 @@ export function createPersistedValue({
|
||||
serialize,
|
||||
deserialize,
|
||||
saveDefaultValue = false,
|
||||
onChange,
|
||||
}) {
|
||||
const defaultSerialized = serialize(defaultValue);
|
||||
|
||||
@@ -60,11 +62,13 @@ export function createPersistedValue({
|
||||
set(v) {
|
||||
value = v;
|
||||
debouncedWrite(v);
|
||||
onChange?.(v);
|
||||
},
|
||||
/** @param {T} v */
|
||||
setImmediate(v) {
|
||||
value = v;
|
||||
write(v);
|
||||
onChange?.(v);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user