Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.5.5/schema.json",
"$schema": "https://biomejs.dev/schemas/2.5.8/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
Expand Down
49 changes: 39 additions & 10 deletions src/components/configure-sections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ export const ResetIndicator = memo(function ResetIndicator({
onClick={onReset}
className="size-5 rounded-full text-muted-foreground hover:text-primary hover:bg-muted/80 p-0"
>
<RotateCcw aria-hidden="true" data-icon="inline-start" className="size-3" />
<RotateCcw
aria-hidden="true"
data-icon="inline-start"
className="size-3"
/>
</Button>
);
});
Expand Down Expand Up @@ -101,7 +105,10 @@ export const GrowthSeasonalitySection = memo(function GrowthSeasonalitySection({
</FieldLabel>
<Tooltip>
<TooltipTrigger className="cursor-pointer">
<HelpCircle aria-hidden="true" className="size-3.5 text-muted-foreground" />
<HelpCircle
aria-hidden="true"
className="size-3.5 text-muted-foreground"
/>
</TooltipTrigger>
<TooltipContent>
Linear for standard trend, Logistic for bounded growth.
Expand All @@ -120,7 +127,11 @@ export const GrowthSeasonalitySection = memo(function GrowthSeasonalitySection({
onConfigChange({ growth: val as "linear" | "logistic" | "flat" })
}
>
<SelectTrigger id="growth" aria-label="Growth Model" className="h-9 text-xs">
<SelectTrigger
id="growth"
aria-label="Growth Model"
className="h-9 text-xs"
>
<SelectValue />
</SelectTrigger>
<SelectContent>
Expand All @@ -147,7 +158,10 @@ export const GrowthSeasonalitySection = memo(function GrowthSeasonalitySection({
</FieldLabel>
<Tooltip>
<TooltipTrigger className="cursor-pointer">
<HelpCircle aria-hidden="true" className="size-3.5 text-muted-foreground" />
<HelpCircle
aria-hidden="true"
className="size-3.5 text-muted-foreground"
/>
</TooltipTrigger>
<TooltipContent>
Additive (+) or Multiplicative (×) variations.
Expand All @@ -174,7 +188,11 @@ export const GrowthSeasonalitySection = memo(function GrowthSeasonalitySection({
})
}
>
<SelectTrigger id="seasonality_mode" aria-label="Seasonality Mode" className="h-9 text-xs">
<SelectTrigger
id="seasonality_mode"
aria-label="Seasonality Mode"
className="h-9 text-xs"
>
<SelectValue />
</SelectTrigger>
<SelectContent>
Expand Down Expand Up @@ -220,7 +238,11 @@ export const GrowthSeasonalitySection = memo(function GrowthSeasonalitySection({
val && onForecastParamsChange({ freq: val })
}
>
<SelectTrigger id="freq" aria-label="Frequency" className="h-9 text-xs">
<SelectTrigger
id="freq"
aria-label="Frequency"
className="h-9 text-xs"
>
<SelectValue />
</SelectTrigger>
<SelectContent>
Expand Down Expand Up @@ -259,7 +281,11 @@ export const GrowthSeasonalitySection = memo(function GrowthSeasonalitySection({
})
}
>
<SelectTrigger id="country_holidays" aria-label="Built-in Country Holidays" className="h-9 text-xs">
<SelectTrigger
id="country_holidays"
aria-label="Built-in Country Holidays"
className="h-9 text-xs"
>
<SelectValue placeholder="Select country…" />
</SelectTrigger>
<SelectContent className="max-h-56">
Expand Down Expand Up @@ -351,7 +377,8 @@ export const CVSplitSection = memo(function CVSplitSection({
Initial Training
</Label>
<span className="font-mono text-muted-foreground text-[11px] tabular-nums">
{cvSplit.initialLabel || cvSplit.initialStr} ({(cvSplit.initialPct * 100).toFixed(0)}%)
{cvSplit.initialLabel || cvSplit.initialStr} (
{(cvSplit.initialPct * 100).toFixed(0)}%)
</span>
Comment on lines 379 to 382
</div>
<Slider
Expand All @@ -370,7 +397,8 @@ export const CVSplitSection = memo(function CVSplitSection({
Forecast Horizon
</Label>
<span className="font-mono text-muted-foreground text-[11px] tabular-nums">
{cvSplit.horizonLabel || cvSplit.horizonStr} ({(cvSplit.horizonPct * 100).toFixed(0)}%)
{cvSplit.horizonLabel || cvSplit.horizonStr} (
{(cvSplit.horizonPct * 100).toFixed(0)}%)
</span>
</div>
<Slider
Expand All @@ -389,7 +417,8 @@ export const CVSplitSection = memo(function CVSplitSection({
Cutoff Step Period
</Label>
<span className="font-mono text-muted-foreground text-[11px] tabular-nums">
{cvSplit.periodLabel || cvSplit.periodStr} ({(cvSplit.periodPct * 100).toFixed(0)}%)
{cvSplit.periodLabel || cvSplit.periodStr} (
{(cvSplit.periodPct * 100).toFixed(0)}%)
</span>
</div>
<Slider
Expand Down
53 changes: 42 additions & 11 deletions src/components/cv-config-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,41 @@ export function CVConfigDialog({

const handleInitialChange = (val: number | readonly number[]) => {
const targetInit = Array.isArray(val) ? val[0] : (val as number);
const newSplit = constrainCVSplit(totalDays, targetInit, horizPct, undefined, freq);
const newSplit = constrainCVSplit(
totalDays,
targetInit,
horizPct,
undefined,
freq,
);
setInitPct(newSplit.initialPct);
setHorizPct(newSplit.horizonPct);
setPerPct(newSplit.periodPct);
};

const handleHorizonChange = (val: number | readonly number[]) => {
const targetHoriz = Array.isArray(val) ? val[0] : (val as number);
const newSplit = constrainCVSplit(totalDays, initPct, targetHoriz, undefined, freq);
const newSplit = constrainCVSplit(
totalDays,
initPct,
targetHoriz,
undefined,
freq,
);
setInitPct(newSplit.initialPct);
setHorizPct(newSplit.horizonPct);
setPerPct(newSplit.periodPct);
};

const handlePeriodChange = (val: number | readonly number[]) => {
const targetPer = Array.isArray(val) ? val[0] : (val as number);
const newSplit = constrainCVSplit(totalDays, initPct, horizPct, targetPer, freq);
const newSplit = constrainCVSplit(
totalDays,
initPct,
horizPct,
targetPer,
freq,
);
setInitPct(newSplit.initialPct);
setHorizPct(newSplit.horizonPct);
setPerPct(newSplit.periodPct);
Expand Down Expand Up @@ -141,20 +159,26 @@ export function CVConfigDialog({
<span className="flex items-center gap-1.5">
<span className="size-2.5 rounded-full bg-primary inline-block" />
Training:{" "}
<strong className="text-foreground">{split.initialLabel || split.initialStr}</strong>{" "}
<strong className="text-foreground">
{split.initialLabel || split.initialStr}
</strong>{" "}
({(split.initialPct * 100).toFixed(0)}%)
</span>
<span className="flex items-center gap-1.5">
<span className="size-2.5 rounded-full bg-chart-2 inline-block" />
Horizon:{" "}
<strong className="text-foreground">{split.horizonLabel || split.horizonStr}</strong>{" "}
<strong className="text-foreground">
{split.horizonLabel || split.horizonStr}
</strong>{" "}
({(split.horizonPct * 100).toFixed(0)}%)
</span>
<span className="flex items-center gap-1.5">
<span className="size-2.5 rounded-full bg-muted-foreground/60 inline-block" />
Step:{" "}
<strong className="text-foreground">{split.periodLabel || split.periodStr}</strong> (
{(split.periodPct * 100).toFixed(0)}%)
<strong className="text-foreground">
{split.periodLabel || split.periodStr}
</strong>{" "}
({(split.periodPct * 100).toFixed(0)}%)
</span>
</div>
</div>
Expand All @@ -168,7 +192,8 @@ export function CVConfigDialog({
Initial Training Split
</FieldLabel>
<span className="font-mono text-muted-foreground tabular-nums">
{split.initialLabel || split.initialStr} ({(split.initialPct * 100).toFixed(0)}%)
{split.initialLabel || split.initialStr} (
{(split.initialPct * 100).toFixed(0)}%)
</span>
Comment on lines 194 to 197
</div>
<Slider
Expand All @@ -188,7 +213,8 @@ export function CVConfigDialog({
Forecast Horizon
</FieldLabel>
<span className="font-mono text-muted-foreground tabular-nums">
{split.horizonLabel || split.horizonStr} ({(split.horizonPct * 100).toFixed(0)}%)
{split.horizonLabel || split.horizonStr} (
{(split.horizonPct * 100).toFixed(0)}%)
</span>
</div>
<Slider
Expand All @@ -208,7 +234,8 @@ export function CVConfigDialog({
Cutoff Step Period
</FieldLabel>
<span className="font-mono text-muted-foreground tabular-nums">
{split.periodLabel || split.periodStr} ({(split.periodPct * 100).toFixed(0)}%)
{split.periodLabel || split.periodStr} (
{(split.periodPct * 100).toFixed(0)}%)
</span>
</div>
<Slider
Expand Down Expand Up @@ -237,7 +264,11 @@ export function CVConfigDialog({
onClick={handleConfirm}
className="text-xs font-bold"
>
<Play aria-hidden="true" data-icon="inline-start" className="fill-current" />
<Play
aria-hidden="true"
data-icon="inline-start"
className="fill-current"
/>
Run Cross-Validation
</Button>
</DialogFooter>
Expand Down
15 changes: 12 additions & 3 deletions src/components/history-sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,10 @@ export function HistorySheet({
<div className="flex-1 overflow-y-auto py-4 space-y-4 pr-1">
{history.length === 0 ? (
<div className="flex flex-col items-center justify-center h-64 text-center p-6 border border-dashed rounded-xl bg-muted/20">
<History aria-hidden="true" className="size-10 text-muted-foreground/50 mb-3" />
<History
aria-hidden="true"
className="size-10 text-muted-foreground/50 mb-3"
/>
<p className="text-sm font-semibold text-foreground">
No History Yet
</p>
Expand Down Expand Up @@ -158,7 +161,10 @@ export function HistorySheet({
<div className="flex flex-col gap-1">
<div className="flex items-center gap-1.5 flex-wrap">
<span className="font-bold text-xs text-foreground flex items-center gap-1">
<Database aria-hidden="true" className="size-3.5 text-primary" />
<Database
aria-hidden="true"
className="size-3.5 text-primary"
/>
{entry.datasetName}
</span>
<Badge
Expand Down Expand Up @@ -304,7 +310,10 @@ export function HistorySheet({
onClick={() => handleSelect(entry)}
className="w-full text-xs gap-1.5 h-8 font-semibold mt-1"
>
<RotateCcw aria-hidden="true" className="size-3.5 text-primary" />
<RotateCcw
aria-hidden="true"
className="size-3.5 text-primary"
/>
Re-run / Load Config
</Button>
</CardContent>
Expand Down
10 changes: 8 additions & 2 deletions src/components/loading-overlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ export function LoadingOverlay({
className="fixed inset-0 z-50 flex flex-col items-center justify-center bg-background/80 backdrop-blur-md transition-opacity animate-in fade-in duration-200 outline-none"
>
<div className="flex flex-col items-center gap-4 rounded-2xl border border-border/60 bg-card p-6 shadow-2xl max-w-sm w-full mx-4 text-center">
<Spinner aria-hidden="true" className="size-8 text-primary animate-spin" />
<Spinner
aria-hidden="true"
className="size-8 text-primary animate-spin"
/>

<div className="flex flex-col gap-1 w-full">
<Badge
Expand Down Expand Up @@ -93,7 +96,10 @@ export function LoadingOverlay({
variant="secondary"
className="gap-1.5 text-[11px] py-1 px-3 bg-muted/80 text-muted-foreground border border-border/50"
>
<ShieldCheck aria-hidden="true" className="size-3.5 text-emerald-500" />
<ShieldCheck
aria-hidden="true"
className="size-3.5 text-emerald-500"
/>
<span>Processing locally via WebAssembly — 100% Private</span>
</Badge>

Expand Down
Loading