mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-05-02 02:20:00 -07:00
app: add chart scroll buttons
This commit is contained in:
@@ -4,6 +4,7 @@ export function Box({
|
||||
flex = true,
|
||||
absolute,
|
||||
padded = true,
|
||||
spaced = true,
|
||||
children,
|
||||
dark,
|
||||
classes,
|
||||
@@ -11,6 +12,7 @@ export function Box({
|
||||
flex?: boolean;
|
||||
absolute?: "top" | "bottom";
|
||||
padded?: boolean;
|
||||
spaced?: boolean;
|
||||
dark?: boolean;
|
||||
classes?: string;
|
||||
} & ParentProps) {
|
||||
@@ -39,7 +41,8 @@ export function Box({
|
||||
>
|
||||
<div
|
||||
class={classPropToString([
|
||||
flex && "flex w-full space-x-2",
|
||||
flex && "flex w-full",
|
||||
spaced && "space-x-2",
|
||||
padded && "p-1.5",
|
||||
])}
|
||||
>
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import { ONE_DAY_IN_MS } from "/src/scripts/utils/time";
|
||||
import { classPropToString } from "/src/solid/classes";
|
||||
import { createRWS } from "/src/solid/rws";
|
||||
|
||||
import { GENESIS_DAY } from "../../../../../scripts/lightweightCharts/whitespace";
|
||||
import { Box } from "../../box";
|
||||
import { Scrollable } from "../../scrollable";
|
||||
|
||||
const MULTIPLIER = 0.002;
|
||||
const DELAY = 10;
|
||||
const LEFT = -1;
|
||||
const RIGHT = 1;
|
||||
|
||||
export function TimeScale({
|
||||
scale,
|
||||
charts,
|
||||
@@ -16,30 +22,82 @@ export function TimeScale({
|
||||
|
||||
const disabled = createMemo(() => charts().length === 0);
|
||||
|
||||
const scrollDirection = createRWS(0);
|
||||
|
||||
const timeScale = createMemo(() => {
|
||||
const chart = charts().at(0);
|
||||
if (!chart) return undefined;
|
||||
return chart.timeScale();
|
||||
});
|
||||
|
||||
const interval = setInterval(() => {
|
||||
const time = timeScale();
|
||||
|
||||
if (!time) return;
|
||||
|
||||
const direction = scrollDirection();
|
||||
|
||||
if (!direction) return;
|
||||
|
||||
const range = time.getVisibleLogicalRange();
|
||||
|
||||
if (!range) return;
|
||||
|
||||
const speed = (range.to - range.from) * MULTIPLIER * direction;
|
||||
|
||||
// @ts-ignore
|
||||
range.from += speed;
|
||||
// @ts-ignore
|
||||
range.to += speed;
|
||||
|
||||
time.setVisibleLogicalRange(range);
|
||||
}, DELAY);
|
||||
|
||||
onCleanup(() => clearInterval(interval));
|
||||
|
||||
return (
|
||||
<Box dark padded={false} classes="short:hidden">
|
||||
<Box dark padded={false} spaced={false} classes="short:hidden">
|
||||
<div class="flex items-center p-1.5">
|
||||
<Button
|
||||
square
|
||||
disabled={disabled}
|
||||
onClick={() => scrollDirection.set((v) => (v === LEFT ? 0 : LEFT))}
|
||||
>
|
||||
<Show
|
||||
when={scrollDirection() === LEFT}
|
||||
fallback={<IconTablerPlayerTrackPrevFilled />}
|
||||
>
|
||||
<IconTablerPlayerPauseFilled />
|
||||
</Show>
|
||||
</Button>
|
||||
</div>
|
||||
<div class="border-lighter border-l" />
|
||||
<Scrollable classes="p-1.5 space-x-2">
|
||||
<Switch>
|
||||
<Match when={scale() === "date"}>
|
||||
<Button
|
||||
minWidth
|
||||
disabled={disabled}
|
||||
onClick={() => setTimeScale({ scale: scale(), charts })}
|
||||
>
|
||||
All Time
|
||||
</Button>
|
||||
<Button
|
||||
minWidth
|
||||
disabled={disabled}
|
||||
onClick={() => setTimeScale({ scale: scale(), charts, days: 7 })}
|
||||
>
|
||||
1 Week
|
||||
</Button>
|
||||
<Button
|
||||
minWidth
|
||||
disabled={disabled}
|
||||
onClick={() => setTimeScale({ scale: scale(), charts, days: 30 })}
|
||||
>
|
||||
1 Month
|
||||
</Button>
|
||||
<Button
|
||||
minWidth
|
||||
disabled={disabled}
|
||||
onClick={() =>
|
||||
setTimeScale({ scale: scale(), charts, days: 3 * 30 })
|
||||
@@ -48,6 +106,7 @@ export function TimeScale({
|
||||
3 Months
|
||||
</Button>
|
||||
<Button
|
||||
minWidth
|
||||
disabled={disabled}
|
||||
onClick={() =>
|
||||
setTimeScale({ scale: scale(), charts, days: 6 * 30 })
|
||||
@@ -56,6 +115,7 @@ export function TimeScale({
|
||||
6 Months
|
||||
</Button>
|
||||
<Button
|
||||
minWidth
|
||||
disabled={disabled}
|
||||
onClick={() =>
|
||||
setTimeScale({
|
||||
@@ -72,6 +132,7 @@ export function TimeScale({
|
||||
Year To Date
|
||||
</Button>
|
||||
<Button
|
||||
minWidth
|
||||
disabled={disabled}
|
||||
onClick={() =>
|
||||
setTimeScale({ scale: scale(), charts, days: 365 })
|
||||
@@ -80,6 +141,7 @@ export function TimeScale({
|
||||
1 Year
|
||||
</Button>
|
||||
<Button
|
||||
minWidth
|
||||
disabled={disabled}
|
||||
onClick={() =>
|
||||
setTimeScale({ scale: scale(), charts, days: 2 * 365 })
|
||||
@@ -88,6 +150,7 @@ export function TimeScale({
|
||||
2 Years
|
||||
</Button>
|
||||
<Button
|
||||
minWidth
|
||||
disabled={disabled}
|
||||
onClick={() =>
|
||||
setTimeScale({ scale: scale(), charts, days: 4 * 365 })
|
||||
@@ -96,6 +159,7 @@ export function TimeScale({
|
||||
4 Years
|
||||
</Button>
|
||||
<Button
|
||||
minWidth
|
||||
disabled={disabled}
|
||||
onClick={() =>
|
||||
setTimeScale({ scale: scale(), charts, days: 8 * 365 })
|
||||
@@ -113,6 +177,7 @@ export function TimeScale({
|
||||
>
|
||||
{(year) => (
|
||||
<Button
|
||||
minWidth
|
||||
disabled={disabled}
|
||||
onClick={() => setTimeScale({ scale: scale(), charts, year })}
|
||||
>
|
||||
@@ -122,10 +187,10 @@ export function TimeScale({
|
||||
</For>
|
||||
</Match>
|
||||
<Match when={scale() === "height"}>
|
||||
<Button disabled={() => true} onClick={() => {}}>
|
||||
<Button minWidth disabled={() => true} onClick={() => {}}>
|
||||
24h
|
||||
</Button>
|
||||
<Button disabled={() => true} onClick={() => {}}>
|
||||
<Button minWidth disabled={() => true} onClick={() => {}}>
|
||||
48h
|
||||
</Button>
|
||||
<For
|
||||
@@ -136,6 +201,7 @@ export function TimeScale({
|
||||
>
|
||||
{(i) => (
|
||||
<Button
|
||||
minWidth
|
||||
disabled={disabled}
|
||||
onClick={() =>
|
||||
setTimeScale({
|
||||
@@ -155,6 +221,21 @@ export function TimeScale({
|
||||
</Match>
|
||||
</Switch>
|
||||
</Scrollable>
|
||||
<div class="border-lighter border-l" />
|
||||
<div class="flex items-center p-1.5">
|
||||
<Button
|
||||
square
|
||||
disabled={disabled}
|
||||
onClick={() => scrollDirection.set((v) => (v === RIGHT ? 0 : RIGHT))}
|
||||
>
|
||||
<Show
|
||||
when={scrollDirection() === RIGHT}
|
||||
fallback={<IconTablerPlayerTrackNextFilled />}
|
||||
>
|
||||
<IconTablerPlayerPauseFilled />
|
||||
</Show>
|
||||
</Button>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -163,17 +244,26 @@ function Button({
|
||||
onClick,
|
||||
disabled,
|
||||
children,
|
||||
}: ParentProps & { onClick: VoidFunction; disabled: Accessor<boolean> }) {
|
||||
minWidth,
|
||||
square,
|
||||
}: ParentProps & {
|
||||
onClick: VoidFunction;
|
||||
disabled?: Accessor<boolean>;
|
||||
minWidth?: boolean;
|
||||
square?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<button
|
||||
class={classPropToString([
|
||||
disabled()
|
||||
minWidth && "min-w-20",
|
||||
square ? "p-2" : "px-2 py-1.5",
|
||||
disabled?.()
|
||||
? "text-low-contrast"
|
||||
: "hover:bg-orange-50/20 active:scale-95",
|
||||
"min-w-20 flex-shrink-0 flex-grow whitespace-nowrap rounded-lg px-2 py-1.5",
|
||||
"flex-shrink-0 flex-grow whitespace-nowrap rounded-lg",
|
||||
])}
|
||||
onClick={onClick}
|
||||
disabled={disabled()}
|
||||
disabled={disabled?.()}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
|
||||
8
app/src/types/auto-imports.d.ts
vendored
8
app/src/types/auto-imports.d.ts
vendored
@@ -193,8 +193,12 @@ declare global {
|
||||
const IconTablerPigMoney: typeof import('~icons/tabler/pig-money.jsx')['default']
|
||||
const IconTablerPlay: (typeof import("~icons/tabler/play.jsx"))["default"]
|
||||
const IconTablerPlayCard: typeof import('~icons/tabler/play-card.jsx')['default']
|
||||
const IconTablerPlayerPauseFilled: (typeof import("~icons/tabler/player-pause-filled.jsx"))["default"]
|
||||
const IconTablerPlayerPlayFilled: (typeof import("~icons/tabler/player-play-filled.jsx"))["default"]
|
||||
const IconTablerPlayerPauseFilled: typeof import('~icons/tabler/player-pause-filled.jsx')['default']
|
||||
const IconTablerPlayerPlayFilled: typeof import('~icons/tabler/player-play-filled.jsx')['default']
|
||||
const IconTablerPlayerTrackNext: typeof import('~icons/tabler/player-track-next.jsx')['default']
|
||||
const IconTablerPlayerTrackNextFilled: typeof import('~icons/tabler/player-track-next-filled.jsx')['default']
|
||||
const IconTablerPlayerTrackPrev: typeof import('~icons/tabler/player-track-prev.jsx')['default']
|
||||
const IconTablerPlayerTrackPrevFilled: typeof import('~icons/tabler/player-track-prev-filled.jsx')['default']
|
||||
const IconTablerPlus: typeof import('~icons/tabler/plus.jsx')['default']
|
||||
const IconTablerQrCode: typeof import('~icons/tabler/qr-code.jsx')['default']
|
||||
const IconTablerQrcode: typeof import('~icons/tabler/qrcode.jsx')['default']
|
||||
|
||||
Reference in New Issue
Block a user