mirror of
https://github.com/baairon/torlink.git
synced 2026-07-08 18:28:22 +02:00
feat: wordmark + progress-bar sheen, dark-violet svg base, readme refinements
This commit is contained in:
@@ -1,13 +1,9 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Text } from "ink";
|
||||
import { COLOR, RULE, lerpHex } from "../theme";
|
||||
import { SHEEN_PEAK, SHEEN_TICK_MS, sheenCenter, sheenIntensity, sheenPeriod } from "../sheen";
|
||||
|
||||
const DEEP = "#7c5cd6";
|
||||
const SHEEN_PEAK = "#f4efff";
|
||||
const RADIUS = 3.5;
|
||||
const GAP = 8;
|
||||
const MAX_SHEEN = 0.9;
|
||||
const TICK_MS = 90;
|
||||
|
||||
interface Run {
|
||||
color: string;
|
||||
@@ -55,7 +51,7 @@ export function ProgressBar({
|
||||
const [tick, setTick] = useState(0);
|
||||
useEffect(() => {
|
||||
if (!animate) return;
|
||||
const timer = setInterval(() => setTick((v) => v + 1), TICK_MS);
|
||||
const timer = setInterval(() => setTick((v) => v + 1), SHEEN_TICK_MS);
|
||||
timer.unref?.();
|
||||
return () => clearInterval(timer);
|
||||
}, [animate]);
|
||||
@@ -76,15 +72,12 @@ export function ProgressBar({
|
||||
);
|
||||
}
|
||||
|
||||
const period = Math.ceil(width + RADIUS * 2) + GAP;
|
||||
const center = (tick % period) - RADIUS;
|
||||
const period = sheenPeriod(width);
|
||||
const center = sheenCenter(tick, period);
|
||||
const cells = Array.from({ length: filled }, (_, i) => {
|
||||
let c = ramp(i / denom, DEEP, COLOR.accent, COLOR.bright);
|
||||
const d = Math.abs(i - center);
|
||||
if (d < RADIUS) {
|
||||
const intensity = 0.5 * (1 + Math.cos((Math.PI * d) / RADIUS)) * MAX_SHEEN;
|
||||
c = lerpHex(c, SHEEN_PEAK, intensity);
|
||||
}
|
||||
const intensity = sheenIntensity(i, center);
|
||||
if (intensity > 0) c = lerpHex(c, SHEEN_PEAK, intensity);
|
||||
return c;
|
||||
});
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import type { Source, TorrentResult } from "../../sources/types";
|
||||
|
||||
type Mode = "list" | "search" | "detail";
|
||||
|
||||
const PLACEHOLDER = "Search, or paste a magnet…";
|
||||
const PLACEHOLDER = "Search or paste a magnet link…";
|
||||
|
||||
function DetailRow({ label, value }: { label: string; value: ReactNode }) {
|
||||
return (
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// Single source of truth for the animated progress-bar sheen, shared by the
|
||||
// live TUI (src/ui/components/ProgressBar.tsx) and the README SVG generator
|
||||
// (scripts/ansi-to-svg.ts) so the preview renders 1:1 with the terminal.
|
||||
//
|
||||
// The highlight is a cosine bell that sweeps across the filled cells. Position
|
||||
// advances by a fractional SHEEN_SPEED per tick at a fast SHEEN_TICK_MS, so the
|
||||
// peak glides between cells (intensity-interpolated) instead of stepping a whole
|
||||
// cell at a time, while the cells themselves stay discrete (pixelated).
|
||||
|
||||
export const SHEEN_PEAK = "#f4efff";
|
||||
export const SHEEN_RADIUS = 4.5; // bell half-width, in cells
|
||||
export const SHEEN_GAP = 8; // dark cells between sweeps
|
||||
export const SHEEN_TICK_MS = 40; // frame interval (~25fps)
|
||||
export const SHEEN_SPEED = 0.45; // cells advanced per tick (~11 cells/sec)
|
||||
export const SHEEN_MAX = 0.9; // peak blend toward SHEEN_PEAK
|
||||
|
||||
/** Total sweep cycle length in cells, for a bar `width` cells wide. */
|
||||
export function sheenPeriod(width: number): number {
|
||||
return Math.ceil(width + SHEEN_RADIUS * 2) + SHEEN_GAP;
|
||||
}
|
||||
|
||||
/** Fractional center of the bell at a given tick (loops over `period`). */
|
||||
export function sheenCenter(tick: number, period: number): number {
|
||||
return ((tick * SHEEN_SPEED) % period) - SHEEN_RADIUS;
|
||||
}
|
||||
|
||||
/** Sheen intensity (0..SHEEN_MAX) for cell `i` given the bell `center`. */
|
||||
export function sheenIntensity(i: number, center: number): number {
|
||||
const d = Math.abs(i - center);
|
||||
if (d >= SHEEN_RADIUS) return 0;
|
||||
return 0.5 * (1 + Math.cos((Math.PI * d) / SHEEN_RADIUS)) * SHEEN_MAX;
|
||||
}
|
||||
|
||||
/** Ticks in one full visual loop, for sampling the SVG flipbook 1:1. */
|
||||
export function sheenLoopTicks(period: number): number {
|
||||
return Math.round(period / SHEEN_SPEED);
|
||||
}
|
||||
@@ -50,7 +50,7 @@ export function Splash() {
|
||||
width={barWidth}
|
||||
value=""
|
||||
editing
|
||||
placeholder="Search, or paste a magnet…"
|
||||
placeholder="Search or paste a magnet link…"
|
||||
onSubmit={submitQuery}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user