mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-30 09:30:00 -07:00
website: snap
This commit is contained in:
@@ -81,13 +81,13 @@
|
||||
* Relative patterns by capability:
|
||||
* Unrealized patterns by capability level
|
||||
* @typedef {Brk.LossNetNuplProfitPattern} BasicRelativePattern
|
||||
* @typedef {Brk.GrossInvestedInvestorLossNetNuplProfitSentimentPattern2} FullRelativePattern
|
||||
* @typedef {Brk.CapitalizedGrossInvestedLossNetNuplProfitSentimentPattern2} FullRelativePattern
|
||||
*
|
||||
* Profitability bucket pattern (supply + realized_cap + unrealized_pnl + nupl)
|
||||
* @typedef {Brk.NuplRealizedSupplyUnrealizedPattern} RealizedSupplyPattern
|
||||
*
|
||||
* Realized pattern (full: cap + gross + capitalized + loss + mvrv + net + peak + price + profit + sell + sopr)
|
||||
* @typedef {Brk.CapGrossInvestorLossMvrvNetPeakPriceProfitSellSoprPattern} RealizedPattern
|
||||
* @typedef {Brk.CapCapitalizedGrossLossMvrvNetPeakPriceProfitSellSoprPattern} RealizedPattern
|
||||
*
|
||||
* Transfer volume pattern (block + cumulative + inProfit/inLoss + sum windows)
|
||||
* @typedef {Brk.AverageBlockCumulativeInSumPattern} TransferVolumePattern
|
||||
@@ -242,19 +242,6 @@
|
||||
* @typedef {CohortFull | CohortLongTerm} CohortWithNuplPercentiles
|
||||
* @typedef {{ name: string, title: string, list: readonly CohortWithNuplPercentiles[], all: CohortAll }} CohortGroupWithNuplPercentiles
|
||||
*
|
||||
* Cohorts with RealizedWithExtras (realizedCapRelToOwnMarketCap + realizedProfitToLossRatio)
|
||||
* @typedef {CohortAll | CohortFull | CohortWithPercentiles} CohortWithRealizedExtras
|
||||
*
|
||||
* Cohorts with circulating supply relative series (supplyRelToCirculatingSupply etc.)
|
||||
* These have GlobalRelativePattern or FullRelativePattern (same as RelativeWithMarketCap/RelativeWithNupl)
|
||||
* @typedef {CohortFull | CohortLongTerm | CohortWithAdjusted | CohortBasicWithMarketCap} UtxoCohortWithCirculatingSupplyRelative
|
||||
*
|
||||
* Address cohorts with circulating supply relative series (all address amount cohorts have these)
|
||||
* @typedef {AddrCohortObject} AddrCohortWithCirculatingSupplyRelative
|
||||
*
|
||||
* All cohorts with circulating supply relative series
|
||||
* @typedef {UtxoCohortWithCirculatingSupplyRelative | AddrCohortWithCirculatingSupplyRelative} CohortWithCirculatingSupplyRelative
|
||||
*
|
||||
* Delta patterns with absolute + rate rolling windows
|
||||
* @typedef {Brk.AbsoluteRatePattern} DeltaPattern
|
||||
* @typedef {Brk.AbsoluteRatePattern2} FiatDeltaPattern
|
||||
|
||||
@@ -38,6 +38,7 @@ export function initChain(parent, callbacks) {
|
||||
|
||||
olderObserver = new IntersectionObserver(
|
||||
(entries) => {
|
||||
return; // edge fetching disabled for layout debugging
|
||||
if (entries[0].isIntersecting) loadOlder();
|
||||
},
|
||||
{ root: chainEl },
|
||||
@@ -46,6 +47,7 @@ export function initChain(parent, callbacks) {
|
||||
chainEl.addEventListener(
|
||||
"scroll",
|
||||
() => {
|
||||
return; // edge fetching disabled for layout debugging
|
||||
const nearStart =
|
||||
(chainEl.scrollHeight > chainEl.clientHeight &&
|
||||
chainEl.scrollTop <= 50) ||
|
||||
|
||||
@@ -38,32 +38,37 @@ export function createCointimeSection() {
|
||||
},
|
||||
]);
|
||||
|
||||
const prices = /** @type {const} */ ([
|
||||
/** @type {readonly { pattern: PriceRatioPercentilesPattern, name: string, title: (name: string) => string, color: Color, defaultActive: boolean }[]} */
|
||||
const prices = [
|
||||
{
|
||||
pattern: cointimePrices.trueMarketMean,
|
||||
name: "True Market Mean",
|
||||
title: (name) => name,
|
||||
color: colors.trueMarketMean,
|
||||
defaultActive: true,
|
||||
},
|
||||
{
|
||||
pattern: cointimePrices.vaulted,
|
||||
name: "Vaulted",
|
||||
title: (name) => `${name} Price`,
|
||||
color: colors.vaulted,
|
||||
defaultActive: true,
|
||||
},
|
||||
{
|
||||
pattern: cointimePrices.active,
|
||||
name: "Active",
|
||||
title: (name) => `${name} Price`,
|
||||
color: colors.active,
|
||||
defaultActive: true,
|
||||
},
|
||||
{
|
||||
pattern: cointimePrices.cointime,
|
||||
name: "Cointime",
|
||||
title: (name) => `${name} Price`,
|
||||
color: colors.cointime,
|
||||
defaultActive: true,
|
||||
},
|
||||
]);
|
||||
];
|
||||
|
||||
const caps = /** @type {const} */ ([
|
||||
{
|
||||
@@ -187,11 +192,11 @@ export function createCointimeSection() {
|
||||
),
|
||||
],
|
||||
},
|
||||
...prices.map(({ pattern, name, color }) => ({
|
||||
...prices.map(({ pattern, name, title, color }) => ({
|
||||
name,
|
||||
tree: priceRatioPercentilesTree({
|
||||
pattern,
|
||||
title: `${name} Price`,
|
||||
title: title(name),
|
||||
legend: name,
|
||||
color,
|
||||
priceReferences: [
|
||||
|
||||
@@ -254,9 +254,6 @@ export function createSelect({
|
||||
? unsortedChoices.toSorted((a, b) => toLabel(a).localeCompare(toLabel(b)))
|
||||
: unsortedChoices;
|
||||
|
||||
const field = window.document.createElement("div");
|
||||
field.classList.add("field");
|
||||
|
||||
const initialKey = toKey(initialValue);
|
||||
|
||||
/** @param {string} key */
|
||||
@@ -266,56 +263,59 @@ export function createSelect({
|
||||
if (choices.length === 1) {
|
||||
const span = window.document.createElement("span");
|
||||
span.textContent = toLabel(choices[0]);
|
||||
field.append(span);
|
||||
} else {
|
||||
const select = window.document.createElement("select");
|
||||
select.id = id ?? "";
|
||||
select.name = id ?? "";
|
||||
field.append(select);
|
||||
|
||||
/** @param {T} choice */
|
||||
const createOption = (choice) => {
|
||||
const option = window.document.createElement("option");
|
||||
option.value = toKey(choice);
|
||||
option.textContent = toLabel(choice);
|
||||
if (toKey(choice) === initialKey) {
|
||||
option.selected = true;
|
||||
}
|
||||
return option;
|
||||
};
|
||||
|
||||
if (groups) {
|
||||
groups.forEach(({ label, items }) => {
|
||||
const optgroup = window.document.createElement("optgroup");
|
||||
optgroup.label = label;
|
||||
items.forEach((choice) => optgroup.append(createOption(choice)));
|
||||
select.append(optgroup);
|
||||
});
|
||||
} else {
|
||||
choices.forEach((choice) => select.append(createOption(choice)));
|
||||
}
|
||||
|
||||
select.addEventListener("change", () => {
|
||||
onChange?.(fromKey(select.value));
|
||||
});
|
||||
|
||||
const remaining = choices.length - 1;
|
||||
if (remaining > 0) {
|
||||
const small = window.document.createElement("small");
|
||||
small.textContent = `+${remaining}`;
|
||||
field.append(small);
|
||||
const arrow = window.document.createElement("span");
|
||||
arrow.textContent = "↓";
|
||||
field.append(arrow);
|
||||
}
|
||||
|
||||
field.addEventListener("click", (e) => {
|
||||
if (e.target !== select) {
|
||||
select.showPicker();
|
||||
}
|
||||
});
|
||||
return span;
|
||||
}
|
||||
|
||||
const field = window.document.createElement("div");
|
||||
field.classList.add("field");
|
||||
|
||||
const select = window.document.createElement("select");
|
||||
select.id = id ?? "";
|
||||
select.name = id ?? "";
|
||||
field.append(select);
|
||||
|
||||
/** @param {T} choice */
|
||||
const createOption = (choice) => {
|
||||
const option = window.document.createElement("option");
|
||||
option.value = toKey(choice);
|
||||
option.textContent = toLabel(choice);
|
||||
if (toKey(choice) === initialKey) {
|
||||
option.selected = true;
|
||||
}
|
||||
return option;
|
||||
};
|
||||
|
||||
if (groups) {
|
||||
groups.forEach(({ label, items }) => {
|
||||
const optgroup = window.document.createElement("optgroup");
|
||||
optgroup.label = label;
|
||||
items.forEach((choice) => optgroup.append(createOption(choice)));
|
||||
select.append(optgroup);
|
||||
});
|
||||
} else {
|
||||
choices.forEach((choice) => select.append(createOption(choice)));
|
||||
}
|
||||
|
||||
select.addEventListener("change", () => {
|
||||
onChange?.(fromKey(select.value));
|
||||
});
|
||||
|
||||
const remaining = choices.length - 1;
|
||||
if (remaining > 0) {
|
||||
const small = window.document.createElement("small");
|
||||
small.textContent = `+${remaining}`;
|
||||
field.append(small);
|
||||
const arrow = window.document.createElement("span");
|
||||
arrow.textContent = "↓";
|
||||
field.append(arrow);
|
||||
}
|
||||
|
||||
field.addEventListener("click", (e) => {
|
||||
if (e.target !== select) {
|
||||
select.showPicker();
|
||||
}
|
||||
});
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user